前言
- 本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
- 这是源码共读的第19期,链接:第19期 | axios 工具函数
Axios
- 源码地址:axios
- 工具函数文件地址:axios/axios/blob/master/lib/utils.js
工具函数
isArray 是否是数组
var toString = Object.prototype.toString;
// 通过 `toString()` 来获取类型
function isArray(val) {
return toString.call(val) === '[object Array]';
}
isUndefined 是否是Undefined
function isUndefined(val) {
return typeof val === 'undefined';
}
isBuffer 是否是buffer
// 边界判断 null 和 undefined
// 判断 `val`存在构造函数
// 最后通过`Buffer`类的`isBuffer`方法判断
function isBuffer(val) {
return val !== null
&& !isUndefined(val)
&& val.constructor !== null
&& !isUndefined(val.constructor)
&& typeof val.constructor.isBuffer === 'function'
&& val.constructor.isBuffer(val);
}
isFormData 是否是FormData
// `instanceof` 运算符用于检测构造函数的 `prototype` 属性是否出现在某个实例对象的原型链上 --> mdn
function isFormData(val) {
return (typeof FormData !== 'undefined') && (val instanceof FormData);
}
isObject 是否是非 null 对象
// 排除 `null`的情况
function isObject(val) {
return val !== null && typeof val === 'object';
}
isPlainObject 是否是纯对象
function isPlainObject(val) {
if (Object.prototype.toString.call(val) !== '[object Object]') {
return false;
}
var prototype = Object.getPrototypeOf(val);
return prototype === null || prototype === Object.prototype;
}
就是未继承任何属性的对象,可用{}或new Object()或Object.create(null)创建。
isDate 是否是Date
function isDate(val) {
return Object.prototype.toString.call(val) === '[object Date]';
}
isFile 是否是文件类型
function isFile(val) {
return Object.prototype.toString.call(val) === '[object File]';
}
isBlob 是否是Blob
function isBlob(val) {
return Object.prototype.toString.call(val) === '[object Blob]';
}
isFunction 是否是函数
function isFunction(val) {
return Object.prototype.toString.call(val) === '[object Function]';
}
isStream 是否是流
function isStream(val) {
return isObject(val) && isFunction(val.pipe);
}
isURLSearchParams 是否是 URLSearchParams
function isURLSearchParams(val) {
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}
URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串
trim 去除首尾空格
// trim 或者正则
function trim(str) {
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
}
isStandardBrowserEnv 是否是标准浏览器环境
function isStandardBrowserEnv() {
if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
navigator.product === 'NativeScript' ||
navigator.product === 'NS')) {
return false;
}
return (
typeof window !== 'undefined' &&
typeof document !== 'undefined'
);
}
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.
*
* @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);
}
}
}
}
stripBOM 删除UTF-8编码中BOM
/**
* Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
*
* @param {string} content with BOM
* @return {string} content value without BOM
*/
function stripBOM(content) {
if (content.charCodeAt(0) === 0xFEFF) {
content = content.slice(1);
}
return content;
}
BOM全称是Byte Order Mark,它是一个Unicode字符,通常出现在文本的开头,用来标识字节序。UTF-8主要的优点是可以兼容ASCII,但如果使用BOM的话,这个好处就荡然无存了。
inherits 原型继承
/**
* Inherit the prototype methods from one constructor into another
* @param {function} constructor
* @param {function} superConstructor
* @param {object} [props]
* @param {object} [descriptors]
*/
function inherits(constructor, superConstructor, props, descriptors) {
constructor.prototype = Object.create(superConstructor.prototype, descriptors);
constructor.prototype.constructor = constructor;
props && Object.assign(constructor.prototype, props);
}
这里不难理解,只要把prototype操作好了就可以
toFlatObject 对象碾平
/**
* Resolve object with deep prototype chain to a flat object
* @param {Object} sourceObj source object
* @param {Object} [destObj]
* @param {Function} [filter]
* @returns {Object}
*/
function toFlatObject(sourceObj, destObj, filter) {
var props;
var i;
var prop;
var merged = {};
destObj = destObj || {};
do {
props = Object.getOwnPropertyNames(sourceObj);
i = props.length;
while (i-- > 0) {
prop = props[i];
if (!merged[prop]) {
destObj[prop] = sourceObj[prop];
merged[prop] = true;
}
}
sourceObj = Object.getPrototypeOf(sourceObj);
} while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
return destObj;
}
将深度对象变成平面对象
toArray 将类数组转数组
/**
* Returns new array from array like object
* @param {*} [thing]
* @returns {Array}
*/
function toArray(thing) {
if (!thing) return null;
var i = thing.length;
if (isUndefined(i)) return null;
var arr = new Array(i);
while (i-- > 0) {
arr[i] = thing[i];
}
return arr;
}
类数组:比如集合,比如我们获取标签集合document.querySelectorAll('li')得到的是标签集合,它不具备数组所有特性,比如.map方法
isTypedArray 是否是Uint8Array
// eslint-disable-next-line func-names
var isTypedArray = (function(TypedArray) {
// eslint-disable-next-line func-names
return function(thing) {
return TypedArray && thing instanceof TypedArray;
};
})(typeof Uint8Array !== 'undefined' && Object.getPrototypeOf(Uint8Array));
Uint8Array 数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。