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.最后直接把键与键值添加到对象上

 作用:

  利用递归多个对象合并,相同属性后面的覆盖前面的。

相关