ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

axios源码分析--基础工具函数

2022-01-13 23:02:24  阅读:154  来源: 互联网

标签:function axios return val -- Object object 源码 toString


1.目标

学习axios源码中实用的工具函数

2.源码分析

2.1 isArray 判断数组

var toString = Object.prototype.toString;

 // 通过Object.prototype.toString来获取每个对象的类型
function isArray(val) {
  return toString.call(val) === '[object Array]';
}

2.2 isUndefined 判断Undefined

// 如果要判断是否是null,使用Object.prototype.toString
function isUndefined(val) {
  return typeof val === 'undefined';
}

2.3 isBuffer 判断Buffer

// a.判断val不是null和undefined
// b.因为Buffer本身是一个类,所以要判断它是否存在构造函数
// c.通过自身的isBuffer判断
// 在node中使用,Buffer.from('a')
function isBuffer(val) {
  return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
    && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
}

2.4 isArrayBuffer 判断ArrayBuffer

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

2.5 isFormData 判断FormData

// 先判断typeof FormData !== 'undefined',猜测原因是为了兼容IE,相关链接:https://stackoverflow.com/questions/19486597/formdata-is-undefined-in-ie-only
function isFormData(val) {
  return (typeof FormData !== 'undefined') && (val instanceof FormData);
}

2.6 isArrayBufferView判断ArrayBufferView

function isArrayBufferView(val) {
  var result;
  // 此处主要是为了兼容IE9及以下
  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
    result = ArrayBuffer.isView(val);
  } else {
    result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
  }
  return result;
}

2.7 isString判断String

function isString(val) {
  return typeof val === 'string';
}

2.8 isNumber判断Number

function isNumber(val) {
  return typeof val === 'number';
}

2.9 isObject判断Object

// 看了下测试用例,数组也算对象,如果真实只检测object的话,还建议使用 Object.prototype.toString
function isObject(val) {
  return val !== null && typeof val === 'object';
}

2.10 isPlainObject判断PlainObject

// plainObject翻译为中文即为纯对象,所谓的纯对象,就是该对象是通过{}或new Object()创建的。
// 判断是否为“纯对象”,是为了和其他对象区分开比如说null、数组以及宿主对象(所有的DOM和BOM都是数组对象)等。
// 其实就是判断目标对象的原型是不是`null` 或 `Object.prototype
// jQuery中的isPlainObject() 函数用于判断指定参数是否是一个纯粹的对象,返回值为Boolean类型。
//“纯粹的对象”,就是通过 { }、new Object()、Object.create(null)  创建的对象。 
//这个方法的作用是为了跟其他的 JavaScript对象如 null,数组,宿主对象(documents),DOM 等作区分,因为这些用 typeof 都会返回object。
var toString = Object.prototype.toString;
function isPlainObject(val) {
  if (toString.call(val) !== '[object Object]') {
    return false;
  }
  // Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)
  // Object.getPrototypeOf:实际上其实是获取当前对象的__proto__
  // Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
  var prototype = Object.getPrototypeOf(val);
  // Object.getPrototypeOf({}.__proto__)
  // Object.create(null)
  return prototype === null || prototype === Object.prototype;
}
// 测试用例
// expect(utils.isPlainObject({})).toEqual(true);
// expect(utils.isPlainObject([])).toEqual(false);
// expect(utils.isPlainObject(null)).toEqual(false);
// expect(utils.isPlainObject(Object.create({}))).toEqual(false);
// let b = {}
// expect(utils.isPlainObject(b).toEqual(true);

2.11 isDate判断Date

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

2.12 isFile判断File

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

2.13 isBlob判断Blob

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

2.14 isFunction判断Function

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

2.15 isStream判断Stream

function isStream(val) {
 // pipe是stream的一个方法,fs.createReadStream源码会使用到,
  return isObject(val) && isFunction(val.pipe);
}

2.16 isURLSearchParams判断URLSearchParams

// URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串
// var paramsString = "q=URLUtils.searchParams&topic=api"
//var searchParams = new URLSearchParams(paramsString);
//searchParams.has("topic") === true; // true
//searchParams.get("topic") === "api"; // true
//searchParams.getAll("topic"); // ["api"]
//searchParams.get("foo") === null; // true
//searchParams.append("topic", "webdev");
//searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
//searchParams.set("topic", "More webdev");
//searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
//searchParams.delete("topic");
//searchParams.toString(); // "q=URLUtils.searchParams"
function isURLSearchParams(val) {
  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}

2.17 trim方法

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

2.18 判断是否事标准浏览器

/**
 * Determine if we're running in a standard browser environment
 *
 * This allows axios to run in a web worker, and react-native.
 * Both environments support XMLHttpRequest, but not fully standard globals.
 *
 * web workers:
 *  typeof window -> undefined
 *  typeof document -> undefined
 *
 * react-native:
 *  navigator.product -> 'ReactNative'
 * nativescript
 * nativescript介绍 https://zhuanlan.zhihu.com/p/29452684
 *  navigator.product -> 'NativeScript' or 'NS'
 */
function isStandardBrowserEnv() {
  if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
                                           navigator.product === 'NativeScript' ||
                                           navigator.product === 'NS')) {
    return false;
  }
  return (
    typeof window !== 'undefined' &&
    typeof document !== 'undefined'
  );
}

2.19 重写forEach方法

/**
 * 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.
 *
 // 在迭代数组和对象的每一项时,执行传入的自定义方法
 // 如果obj是数组,callback执行参数为value, index, and complete array
 // 如果obj是对象,callback执行参数为value, key, and complete object
 // 此覆盖方法貌似只是比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);
      }
    }
  }
}

2.20 merge方法

/**
 * 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;
}

2.21 extend方法

/**
 * Extends object a by mutably adding to it the properties of object b.
 */
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;
}

2.22 stripBOM方法

/**
 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
 */
 // 确定json文件是UTF-8 无BOM编码的的。如果有BOM,会在读取第一行的时候出现乱码。
 // 所谓 BOM,全称是Byte Order Mark,它是一个Unicode字符,通常出现在文本的开头,用来标识字节序。UTF-8主要的优点是可以兼容ASCII,但如果使用BOM的话,这个好处就荡然无存了。
 // 删除UTF-8编码中BOM
function stripBOM(content) {
  if (content.charCodeAt(0) === 0xFEFF) {
    content = content.slice(1);
  }
  return content;
}

3.知识扩展

3.1 判断数据类型的几种方式

// 数组最好使用typeof判断,这样定义()=> {}的方法,会被Object.prototype.toString识别为Object
1.typeof:仅能判断基础数据类型,如:“number”,”string”,”undefined”,”boolean”,“symbol” (ES6新增)六种,”object”类型建议使用Object.prototype.toString判断
2.instanceof 用于判断一个变量是否某个对象的实例,如:Object Array Function
// 所有的均可使用下边方法判断
3.Object.prototype.toString:对于数组、null、对象来说,其关系错综复杂,使用 typeof 都会统一返回 “object” 字符串。所以用此方法来判断

3.2 Buffer相关知识

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

3.3 NodeJS中ArrayBuffer与Buffer的异同

  • ArrayBuffer对象用来表示通用的、固定长度的原始二进制数据缓冲区,是一个字节数组,可读但不可直接写。
  • Buffer 是 Node.JS 中用于操作 ArrayBuffer 的视图,是 TypedArray的一种。

4.总结

附:

1.源码链接

标签:function,axios,return,val,--,Object,object,源码,toString
来源: https://blog.csdn.net/qq_39544148/article/details/122408449

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有