持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
前言
axios是前端主流的http库,基于promise,可以用在浏览器和node.js中使用,为了提高效率,axios使用了一些工具库(utils),这是一个非axios特有的通用帮助函数库,本文对这个文件的重点函数(原型相关)进行解析,可以让我们更好的理解axios源码和学习。
utils.js
var bind = require('./helpers/bind');
开头引入了bind函数,我们看下源码
module.exports = function bind(fn, thisArg) {
return function wrap() {
return fn.apply(thisArg, arguments);
};
};
bind函数接收2个参数,第一个是传入的fn(function),第二个是要给他绑定的this(thisArg),bind函数返回一个wrap方法,wrap中使用了fn.apply方法,会把调用bind()函数的参数传给fn使用,并且使用thisArg作为给定的this
var toString = Object.prototype.toString;
由于大多数toString方法被改写,所以我们通过Object.prototype去拿原始toString方法。
var kindOf = (function(cache) {
return function(thing) {
var str = toString.call(thing);
return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
};
})(Object.create(null));
- 这里的
kindOf是个IIFE方法,通过Object.create(null)新创建了个对象,当作实参传给了匿名函数使用,返回了个方法,如果该参数(thing)不存在,则截取该方法的类型,并返回,如果该参数(thing)已经存在了缓存当中,则直接返回 - 这个方法的核心其实就是通过
Object.prototype.toString.call() + slice,对参数进行截取,并缓存在我们新创建的对象中(Object.create(null))
function kindOfTest(type) {
type = type.toLowerCase();
return function isKindOf(thing) {
return kindOf(thing) === type;
};
kindOfTest方法是一个简单的高阶函数,传一个类型比如string,然后定义好再传一个参数判断是否相等这个类型,内部是通过上面的kindOf()方法进行判断。
function isBuffer(val) {
return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
&& typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
}
- Buffer:Node.js提供的一个二进制缓冲区,常用来处理I/O操作,js没有判断缓冲区的方法,所以用这个函数来判断是不是Buffer
- 这里用到的isUndefined源码:
isUndefined = (val) => typeof val === 'undefined'; - val的原型上如果有
isBuffer方法,会返回boolean,所以也需要判断一下
function isPlainObject(val) {
if (kindOf(val) !== 'object') {
return false;
}
var prototype = Object.getPrototypeOf(val);
return prototype === null || prototype === Object.prototype;
}
- 判断是否为普通对象的方法
- 先看第一步,上面写了
kindOf函数,它的原理是使用了Object.prototype.toString.call()来判断类型([Symbol.toStringTag]),所以也可以判断出null和普通对象的区别 Object.getPrototypeOf()会返回指定对象的原型Object.create(null)的[Symbol.toStringTag]是object,但他的原型对象又是null,这种也属于普通对象- 普通的(几乎所有)
JavaScript对象都是Object的实例,其原型链上最后一个就是指向Object.prototype,只要查找到,肯定就是普通对象
function isStream(val) {
return isObject(val) && isFunction(val.pipe);
}
- 这里是用来判断Stream的方法
isObject = (val) => val !== null && typeof val === 'object';isFunction = (val) => toString.call(val) === '[object Function]';stream有pipe方法,所以这里也拿来判断
function trim(str) {
return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}
- 替代
String.prototype.trim.call方法,如果字符串的这个方法被重写或者找不到,可以通过这一段正则来去除
结语
本文介绍了axios的工具库中部分使用到了原型相关的方法,复习了几个不常用的方法:Object.prototypeof.toString.call、Object.getPrototypeOf,并且涉及到了一些原型链相关的知识,还学习了kindOf这个可以缓存变量类型的函数。