两个箭头函数的演绎
const typeOfTest = type => thing => typeof thing === type;
最开始一看很蒙蔽,很多事情自己不会写这样的代码,说白了还是代码底子不行。可能很多大佬一看就明白了。 先来一个最简单的箭头函数
const f = v => v;
// 等同于
const f = function (v) {
return v;
};
所以我们来类比一下
var typeOfTest = function(type) {
// 也就是把第一个箭头函数后面全部返回即可
return thing => typeof thing === type;
}
这个样子我相信很多人都能看明白了,再进行一步的解析就完事了
var typeOfTest = function(type) {
return function(thing) {
return typeof thing === type;
}
}
再来看一下,其实发现调用typeOfTest会返回一个函数,那么就说明调用完之后还需要调用执行
// 这里其实就是
typeOfTest('undefined')(undefined)
所以就用了下面一系列的函数,这是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');
// 判断是否为一个object对象
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(上卷)》
所以axios在判断是否为对象的时候,先判断是否等于null,再进行typeof的比对。
| 这里其实我发现了axios的一个小bug。typeof NaN的时候,其实返回的也是number.
NaN ,可以翻译为 not a number ,即不是一个数字。 NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),常用来指出数字类型中的错误情况,即:“执行数学运算没有成功,这是返回的结果” 所以有时候我们判断的时候可能要通过 Number.isNaN,而 Number.isNaN 是 ES6 中新增的函数,Number.isNaN()只有对于 NaN 才返回 true,非 NaN 一律返回 false。
| 这里还要关注一下 IsNaN 方法,和 Number.isNaN 的区别 https://juejin.cn/post/6844903507368083469,简单来说 isNaN 之前算是 bug 吧,然后 ES6 新增了 Number.isNaN。
所以上面判断是否为number数值的方法做一个小的调整,先判断一下是否为NaN
const isNumber = (thing) => Number.isNaN(thing)? false: typeOfTest('number')(thing)
拆解第二个两个箭头函数
//这个在顶部单独拎出来的
const {toString} = Object.prototype;
const kindOf = (cache => thing => {
const str = toString.call(thing);
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
})(Object.create(null));
首先提一下 Object.create(null) 就是生成一个空的对象 {}
,创建完kindOf后先传入了一个空对象进行IIFE自执行闭包,cache 由字面意思便可以看出来缓存的意思,也就是传进来的空对象,在执行完闭包之后,cache就一直存在了不会释放掉,也就由了缓存的意思。
| 如果你想进一步了解一下闭包,我之前有整理过一篇非常容易理解的文章可以看一下:https://juejin.cn/post/7120371754274553887
再来看一下Object.prototype.toString
Object.prototype.toString.call(null); // '[object Null]'
Object.prototype.toString.call(undefined); //'[object Undefined]'
Object.prototype.toString.call(123); //'[object Number]'
Object.prototype.toString.call(123n); //'[object BigInt]'
Object.prototype.toString.apply("123"); //'[object String]'
Object.prototype.toString.apply(true); //'[object Boolean]'
Object.prototype.toString.apply(Symbol()); //'[object Symbol]'
Object.prototype.toString.apply({}); // '[object Object]'
Object.prototype.toString.apply([]); // '[object Array]'
Object.prototype.toString.apply(new Date()); // "[object Date]"
Object.prototype.toString.apply(new Function()); // "[object Function]"
Object.prototype.toString.apply(function t() {}); // '[object Function]'
Object.prototype.toString.apply(Math); // '[object Math]'
Object.prototype.toString.apply(new RegExp()); //'[object RegExp]'
通过我的console打印可以非常明确的看到类型标注,这也是上面为什么使用了slice(8, -1)
const kindOf = function (cache) {
return function (thing){
const str = toString.call(thing);
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
})(Object.create(null));
这样再来看这个函数,就非常的清晰了,这里截取了[object Array]
Array
, 从第八位字符串开始到最后。 所有最后总结这个kindOf函数的作用便是,传入一个值,输出一个类型。
再来看一下下面的调用示例
const kindOfTest = (type) => {
type = type.toLowerCase();
return (thing) => kindOf(thing) === type
}
这个函数相对来说就比较好理解,一个箭头函数里面开始执行,第二行最终又返回一个箭头函数。 其实意思便是先传入一个类型,再通过返回的函数,传入某个参数,来判断参数的类型是否与type一致。
// 判断是否为RegExp类型的方法
const isRegExp = kindOfTest('RegExp');
// 判断是否为日期类型的方法
const isDate = kindOfTest('Date');
// 判断是否为ArrayBuffer类型
const isArrayBuffer = kindOfTest('ArrayBuffer');
// 判断是否为文件类型的方法
const isFile = kindOfTest('File');
// 判断是否为Blob类型的方法
const isBlob = kindOfTest('Blob');
// 判断是否为文件列表类型 FileList的方法
const isFileList = kindOfTest('FileList');
// 判断是否为URLSearchParams类型的方法
const isURLSearchParams = kindOfTest('URLSearchParams');
// 判断是否为HTMLFormElement类型的方法
const isHTMLForm = kindOfTest('HTMLFormElement');
数组相关方法
- 判断是否为数组的方法
直接使用Array数组本身中的方法
const {isArray} = Array;