大家好,我是 那个曾经的少年回来了
。10年前我也曾经年轻过,如今已步入被淘汰的年龄,但如下幡然醒悟,所以活在当下,每天努力一点点,来看看2024年的时候自己会是什么样子吧,2024年的前端又会是什么样子,而2024年的中国乃至全球又会变成什么样子,如果你也有想法,那还不赶紧行动起来。期待是美好的,但是更重要的是要为美好而为之奋斗付诸于行动。
最近在读axios的源码,有一些晦涩难懂,于是乎就先来入手一下 axios
的 utils
工具函数, 于是有趣的事情发生了。接下来就跟随我的思路来看看我发现的小问题吧,如果是大佬,就此别过。
1、两个箭头函数的演绎
const typeOfTest = type => thing => typeof thing === type;
最开始我一看很蒙蔽,很多时候自己并不会去写这样的函数,说白了还是自己代码底子不行。可能很多大佬一看就明白了,所以基础很重要,基础很重要,基础很重要。箭头函数算是ES6中新增的。
那我先来一个最简单的箭头函数
const f = v => v; // 等同于 const f = function (v) { return v; };
相信有点JavaScript基础的朋友们应该都能看懂上面的代码,所以参考上面的小例子,来类比一下
const typeOfTest = function(type) { // 也就是把第一个箭头函数后面全部返回即可 return thing => typeof thing === type; }
这个样子我相信很多人都能看明白了,不过此时我们还可以再次拆解,将两个箭头函数都用ES5的写法改写
let typeOfTest = function(type) { return function(thing) { return typeof thing === type; } }
再次看上面的代码,就再清楚不过了,其实发现调用typeOfTest会返回一个函数,那么就说明调用完之后还需要调用执行,而且再次调用还需要传入一个参数
typeOfTest('undefined')(undefined)
2、函数本身的意义
这里其实就是第一次调用先传入一个已知的数据类型,第二次调用再传入参数值,通过 typeof
解析出类型与第一次传入类型进行判断,返回 true
或者 false
。
所以就有了axios源码 utils.js
文件中一系列的函数
// 判断是否为undefined的方法 const isUndefined = typeOfTest('undefined'); // 判断是否为字符串的方法 const isString = typeOfTest('string'); // 判断是否为函数的方法 const isFunction = typeOfTest('function'); // 判断是否为Boolean类型的方法 const isBoolean = thing => thing === true || thing === false; // 我觉得可以添加一个 const isBoolean = typeOfTest('boolean'); // 判断是否为数值类型的方法 const isNumber = typeOfTest('number');
这里我故意将 isNumber
放到最后。
这里其实就是我发现axios中一个小bug。
3、判断是否是number的问题
typeof NaN
的时候,其实返回的也是 number
。
NaN ,可以翻译为 not a number ,即不是一个数字。 NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),常用来指出数字类型中的错误情况,即:“执行数学运算没有成功,这是返回的结果” 所以有时候我们判断的时候可能要通过 Number.isNaN,而 Number.isNaN 是 ES6 中新增的函数,Number.isNaN()只有对于 NaN 才返回 true,非 NaN 一律返回 false。
所以上面判断是否为number数值的方法做一个小的调整,先判断一下是否为NaN
const isNumber = (thing) => Number.isNaN(thing)? false: typeOfTest('number')(thing)
这里还要关注一下 IsNaN 方法,和 Number.isNaN 的区别 juejin.cn/post/684490…。
isNaN(NaN); // true isNaN('A String'); // true isNaN(undefined); // true isNaN({}); // true Number.isNaN('A String'); // false Number.isNaN(undefined); // false Number.isNaN({}); // false Number.isNaN(NaN); // true
我想只有Number.isNaN(NaN)
是我们想要的结果,所以简单的来说 isNaN
方法算是之前JavaScript遗留的 bug 吧,然后 ES6 新增了 Number.isNaN,这个问题从而得到了解决。
4、哪些情况会导致NaN值的产生呢
Number(NaN) // NaN Number(undefined) // NaN Number('abc') // NaN Number('null') // 0 Number('2.45s') // NaN parseFloat(NaN) // NaN parseFloat(undefined) // NaN parseFloat(null) // NaN parseFloat('abc') // NaN parseFloat('2.45s') // 2.45 parseInt(NaN) // NaN parseInt(undefined) // NaN parseInt(null) // NaN parseInt('abc') // NaN parseInt('2.45s') // 2 1+NaN // NaN 1+undefined // NaN 1+null // 1
其实上面要注意一下 Number(null)
的值为0,并且 1+null
的值为 1。
parseInt
和 parseFloat
是将字符串转换为数值,从第一个字符(位置0)开始解析每个字符。而且也是一直解析到末尾,或者解析到遇见一个无效数字或者无效的浮点数字字符为止。
而 Number
可以将任意类型的字符转换为数值类型,根据具体类型进行输出判断,主要的几种判断方式我在上面已经列出。
5、判断是否是对象的方法
但是我发现判断是否是一个对象,这个判断axios倒是特意做了一个判断
const isObject = (thing) => thing !== null && typeof thing === 'object';
typeof null 输出 object:null 作为一个基本数据类型为什么会被 typeof 运算符识别为 object 类型呢?这个 bug 是第一版 Javascript 留下来的,javascript 中不同对象在底层都表示为二进制,而 javascript 中会把二进制前三位都为 0 的判断为 object 类型,而 null 的二进制表示全都是 0,自然前三位也是 0,所以执行 typeof 时会返回 'object'。 ----引用自《你不知道的 javascript(上卷)》
6、总结
- typeof 作为类型判断的两个缺陷
- 判断是否为number类型,要将NaN考虑进去
- 判断是否为object类型,要将null考虑进行
- 箭头函数嵌套的解析,将复杂问题简单化
- 如果不使用typeof判断类型,可以考虑使用
Object.prototype.toString
这也是axios
中使用的一种方式。
- 了解
typeof NaN
输出number的问题
- 了解
typeof null
输出object的问题
我的个人博客:vue.tuokecat.com/blog
我的个人github:github.com/aehyok
我的前端项目:pnpm + monorepo + qiankun + vue3 + vite3 + 工具库、组件库 + 工程化 + 自动化
不断完善中,整体框架都有了
在线预览:vue.tuokecat.com
github源码:github.com/aehyok/vue-…