【若川视野 x 源码共读】第19期 | axios 工具函数

341 阅读4分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。

axios对我们来说在熟悉不过了,可以说是天天用。那么它的源码中有什么可以借鉴的宝贵内容呢?本文分析了axios工具函数的代码,学完可以应用到自己的项目中!

源码地址:github.com/axios/axios

1.toString

var toString = Object.prototype.toString;

toString引用对象原型上的toString方法。

2.isArray判断是否为数组

function isArray(val) {
  return Array.isArray(val);
}

注意:ie8之前不支持isArray

另外判断是不是数组也可以使用:

function isArrayFn (o) {
  return Object.prototype.toString.call(o) === '[object Array]';
  // 或者 return toString(o) ===  '[object Array]'
}

参考文章:www.cnblogs.com/heshan1992/…

3.isUndefined判断是否为undefined

function isUndefined(val) {
  return typeof val === 'undefined';
}

利用typeof , typeof的返回值如下:

    1. 'undefined' --未定义的变量或值

    2. 'boolean'   --布尔类型的变量或值

    3. 'string'    --字符串类型的变量或值

    4. 'number'    --数字类型的变量或值

    5. 'object'    --对象类型的变量或值,或者null(这个是js历史遗留问题,将null作为object类型处理)

    6. 'function'  --函数类型的变量或值
    
    7. 'symbol'    --Symbol类型的变量或者值

利用typeof判断的工具函数还有:

function isString(val) {
  return typeof val === 'string';
}
function isNumber(val) {
  return typeof val === 'number';
}
function isObject(val) {
  return val !== null && typeof val === 'object';
}

4.isBuffer判断是否为buffer

function isBuffer(val) {
  return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
    && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
}

Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

javascript.ruanyifeng.com/nodejs/buff…

5.isArrayBuffer判断是否为ArrayBuffer

function isArrayBuffer(val) {
  return toString.call(val) === '[object ArrayBuffer]';
}

developer.mozilla.org/zh-CN/docs/…

www.cnblogs.com/gradolabs/p…

和这个判断是否为buffer相关的方法是isArrayBufferView:

function isArrayBufferView(val) {
  var result;
  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
    result = ArrayBuffer.isView(val);
  } else {
    result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));
  }
  return result;
}

用来判断ArrayBuffer的视图。参见:Int32Array.prototype.buffer****

6.isFormData判断是否为FormData

function isFormData(val) {
  return toString.call(val) === '[object FormData]';
}

developer.mozilla.org/zh-CN/docs/…

7.isPlainObject判断是否为纯对象

function isPlainObject(val) {
  if (toString.call(val) !== '[object Object]') {
    return false;
  }

  var prototype = Object.getPrototypeOf(val);
  return prototype === null || prototype === Object.prototype;
}

纯粹的对象(通过 "{}" 或者 "new Object" 创建的)

www.cnblogs.com/Renyi-Fan/p…

www.jianshu.com/p/b644bcf93…

8.isDate判断是否是日期对象

function isDate(val) {
  return toString.call(val) === '[object Date]';
}

运用了之前定义的toString方法,对得到的结果进行比较,同样使用这个toString方法的还有:

function isFile(val) {
  return toString.call(val) === '[object File]';
}
function isBlob(val) {
  return toString.call(val) === '[object Blob]';
}
function isFunction(val) {
  return toString.call(val) === '[object Function]';
}
function isURLSearchParams(val) {
  return toString.call(val) === '[object URLSearchParams]';
}

分别判断是否为文件,判断是否为Blob,判断是否为函数,判断是否为URLSearchParams。

9.判断是否为流

function isStream(val) {
  return isObject(val) && isFunction(val.pipe);
}

流是对象,并且有pipe方法。

10.去掉字符串中的空格

function trim(str) {
  return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
}

11.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);
      }
    }
  }
}

如果是数组则for循环每一项,调用fn方法;如果是对象则for in 每个属性,如果是自身属性则调用fn。

12.merge合并对象

function merge(/* obj1, obj2, obj3, ... */) {
  var result = {};
  function assignValue(val, key) {
    // 合并对象存在key,val是一个对象
    if (isPlainObject(result[key]) && isPlainObject(val)) {
      // 调用merge递归
      result[key] = merge(result[key], val);
    } else if (isPlainObject(val)) {
      // 合并对象不存在key,并且是一个对象
      result[key] = merge({}, val);
    } else if (isArray(val)) {
      // 如果val是数组
      result[key] = val.slice();
    } else {
      result[key] = val;
    }
  }
  // 对每一个参数调用forEach
  for (var i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}

13.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;
}

把b的属性赋给a, 如果属性是个函数,需要指定函数的this是则可以指定thisArg。

14.stripBOM 删除BOM

function stripBOM(content) {
  if (content.charCodeAt(0) === 0xFEFF) {
    content = content.slice(1);
  }
  return content;
}

BOM : Byte Order Mark 它是一个Unicode字符,通常出现在文本的开头,用来标识字节序。

学完本文,您可以思考如下问题:

1.js中如何判断变量属于哪种引用数据类型(例如:Array, Function等)

2.如何判断变量是否为文件(File)?

3.是否了解Buffer,ArrayBuffer?

4.如何判断变量是否为FormData?

5.如何使用正则去掉字符串中的空格?

6.编写一个既可以遍历数组又可以遍历对象的方法?

7.如何合并可变个数的对象?

8.js中如何对数组进行深拷贝?(参见merge函数实现步骤)