【第19期】【阅读 axios 源码】 - utils.js 工具函数

211 阅读3分钟

趁着还没开始忙起来 多看点源码,今天进行第二篇源码阅读 axios 工具函数

曾经粗略过过一遍 axios 源码,但是印象已然模糊,这里先根据内容安排先再过一遍 axios 的工具函数

了解到了开源项目中比较重要的文档,CONTRIBUTING.md,表明了如何为 Axios 项目做贡献 其中比较重要的是代码规范 node style guide. 和行为准则 Contributor Covenant Code of Conduct

首先我们遇到第一个函数 —— Object.prototype.toString

toString()方法可以改写,以实现对对象更为具体的描述

下面从所有的工具函数中挑选几个进行解读:

isArray

现阶段源码使用了 Array.isArray() 来替代原先的判断方式 toString.call(val) === '[object Array]'

isBuffer

我们要了解下这里的 Buffer 指的是什么 在 Node.js 中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。 www.runoob.com/nodejs/node…

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

isArrayBufferView

什么是 arrayBuffer

isPlainObject

判断目标对象的原型是不是nullObject.prototype 纯对象:用{}或 new Object()创建的对象。 那么通过 Object.create(null) 创建的对象呢。

isStream

node 中的流 stream 有价值的参考文章

isURLSearchParams

URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。

forEach

集成了 Array 和 Object 的遍历; 对不可迭代对象,先将其包裹成 Array

Object.prototype.hasOwnProperty: 返回一个布尔值,指示对象自身属性中是否具有指定的属性(可枚举、不可枚举均可)

for...in 循环只会遍历可枚举属性

/**
 * Iterate over an Array or an Object invoking a function for each item.
 *
 * If `obj` is an Array callback will be called passing
 * the value, index, and complete array for each item.
 *
 * If 'obj' is an Object callback will be called passing
 * the value, key, and complete object for each property.
 *
 * @param {Object|Array} obj The object to iterate
 * @param {Function} fn The callback to invoke for each item
 */
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);
      }
    }
  }
}

merge

将多个对象进行合并,键相同则使用排在后面的对象中的值

递归调用

小技巧: array.slice() 浅拷贝数组

/**
 * Accepts varargs expecting each argument to be an object, then
 * immutably merges the properties of each object and returns result.
 *
 * When multiple objects contain the same key the later object in
 * the arguments list will take precedence.
 *
 * Example:
 *
 * ```js
 * var result = merge({foo: 123}, {foo: 456});
 * console.log(result.foo); // outputs 456
 * ```
 *
 * @param {Object} obj1 Object to merge
 * @returns {Object} Result of all merge properties
 */
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;
}

extend

将 b 对象上的属性扩展到 a 对象上,并返回 a 对象

/**
 * Extends object a by mutably adding to it the properties of object b.
 *
 * @param {Object} a The object to be extended
 * @param {Object} b The object to copy properties from
 * @param {Object} thisArg The object to bind function to
 * @return {Object} The resulting value of object a
 */
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;
}

Axios 的工具函数源码还是比较简单,但是代码编写风格还是有值得学习借鉴的地方。 通过本次源码阅读,发现了知识点上的一些遗忘,借此机会再好好复习一下。

  • To Do:
    • axios 全部源码,这些工具函数都在那里调用了,起到了什么作用
    • js 基础
      • 函数调用的几种方式复习,包括 call apply bind
      • instance of / typeof
    • 文件类型