axios源码 utils 部分工具方法分析
一.forEach
function forEach(obj, fn) { // Don't bother if no value provided if (obj === null || typeof obj === 'undefined') { return; } // Force an array if not already something iterable if (typeof obj !== 'object') { /*eslint no-param-reassign:0*/ obj = [obj]; } if (isArray(obj)) { // Iterate over array values for (var i = 0, l = obj.length; i < l; i++) { fn.call(null, obj[i], i, obj); } } else { // Iterate over object keys for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { fn.call(null, obj[key], key, obj); } } } }function Test() { this.name = "21"; this.age = 12; } Test.prototype.hello = alert.bind(null); let obj5 = new Test() //for in 会将prototype 方法也遍历
=============================================================
for (let key in obj5) { console.log(key, obj5[key]) }
分析:
1.如果传的值是null 或 undefined 则直接返回
2.如果传的不是对象,则转为数组
3.如果是数组,则遍历调用fn回调,传数组循环的当前值,下标以及整个数组
4.如果是对象,则使用for in遍历对象,因为for in会将原型上的方法也遍历,使用Object.prototype.hasOwnProperty来判断当前属性是否是自身的
作用:
循环遍历每一项,并执行一个回调函数
二.bind
function bind(fn, thisArg) { return function wrap() { var args = new Array(arguments.length); for (var i = 0; i < args.length; i++) { args[i] = arguments[i]; } return fn.apply(thisArg, args); }; };
分析:
返回一个wrap函数,wrap里面将arguments伪数组转为真正数组,apply第二个参数支持数组和伪类,可以不用转
使用apply 改变函数的this指向,一直指向Axios 实例
三.extend
function extend(a, b, thisArg) { forEach(b, function assignValue(val, key) { if (thisArg && typeof val === 'function') { a[key] = bind(val, thisArg); } else { a[key] = val; } }); return a; }
分析:
1. 接收三个参数,a要扩展的对象,b复制属性的对象,thisArg要绑定函数的对象
2. 前面一直想forEach 这个方法为什么重新封装呢,主要后面好多方法需要复用
3. 如果是函数且有this指向thisArg,直接将方法添加到a上
4. 其余以键值对形式添加到a上
作用:
将一个对象上的属性添加到另一个对象上
四. isPlainObject
function isPlainObject(val) { if (toString.call(val) !== '[object Object]') { return false; } var prototype = Object.getPrototypeOf(val); return prototype === null || prototype === Object.prototype; } ========================================================== //纯对象创建方式 // let o = {}; // let obj1 = new Object()
分析:
1.Object.prototype.toString 方法返回 "[object type]",其中 type
是对象的类型,"[object object]"检测当前值是不是一个对象,不是ruturn false
2.Object,getPrototypeOf()方法可以获当前对象的原型
3. 最后一行判断当前对象是不是纯对象。
作用:
判断一个值是不是纯对象
五.merge
function merge(/* obj1, obj2, obj3, ... */) { var result = {}; function assignValue(val, key) { if (isPlainObject(result[key]) && isPlainObject(val)) { result[key] = merge(result[key], val); } else if (isPlainObject(val)) { result[key] = merge({}, val); } else if (isArray(val)) { result[key] = val.slice(); } else { result[key] = val; } } for (var i = 0, l = arguments.length; i < l; i++) { forEach(arguments[i], assignValue); } return result; }
分析:
1.使用forEach方法对每一个参数循环遍历
2.执行assignValue 方法,接收forEach循环传的键值与键,如果是键与键值都是纯对象则添加一个键名并递归
3.如果键值是纯对象,则递归
4.如果键值是数组,则调用数组slice方法,把数组浅拷贝
5.最后直接把键与键值添加到对象上
作用:
利用递归多个对象合并,相同属性后面的覆盖前面的。