axios源码——工具函数utils.js

2023-05-16

文章目录

  • 前言
  • 一、工具函数所在目录
  • 二、判定数据类型的函数
    • 1.isArray(判定数组)
    • 2.isString(判定字符串)
    • 3.isNumber(判定数值)
    • 4.isObject(判定对象)
    • 5.isPlainObject(判定纯对象)
    • 6.isUndefined(判定是否是undefined)
    • 7.isFunction(判定是否是Function)
    • 8.isDate(判定是否是Date对象)
    • 9.isFile(判定是否是File文件对象)
    • 10.isBlob(判定是否是Blob对象)
    • 11.isBuffer(判定是否是Buffer对象)
    • 12.isArrayBuffer(判定是否是ArrayBuffer对象)
    • 13.isFormData(判定是否是FormData对象)
    • 14.isStream(判定是否是Stream)
    • 15.isURLSearchParams(判定是否是URLSearchParams对象)
  • 三、其他常用的工具方法
    • 1.trim(去除首尾空格)
    • 2.isStandardBrowserEnv(判定标准浏览器环境)
    • 3.forEach(遍历对象或数组)
    • 4.merge(合并对象)
    • 5.extend(对象属性扩展)
    • 6.stripBOM(删除UTF-8编码中BOM)
  • 总结


前言

学习源码,可以帮助我们工具基础知识点和提升编程能力。之前分享过vue3中的常用工具函数(戳此链接)。
那今天本文的主角是axios源码中的/lib/utils.js,介绍一下axios库中常用的工具函数


一、工具函数所在目录

axios/lib/utils.js

二、判定数据类型的函数

共用的toString 方法

var toString = Object.prototype.toString;

1.isArray(判定数组)

和vue3源码中判定一样

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

2.isString(判定字符串)

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

3.isNumber(判定数值)

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

4.isObject(判定对象)

注意在js中,null也是一个特殊对象,此时判定要排出null的情况。
此方法同vue3源码中判定对象方法

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

5.isPlainObject(判定纯对象)

纯对象: 用{}或new Object()创建的对象。
此方法同vue3源码中判定纯对象方法

function isPlainObject(val) {
  if (toString.call(val) !== '[object Object]') {
    return false;
  }
  // Object.getPrototypeOf返回指定对象的原型
  // 其实就是判断目标对象的原型是不是`null` 或 `Object.prototype`
  var prototype = Object.getPrototypeOf(val);  
  return prototype === null || prototype === Object.prototype;
}

测试代码如下

// 例子1
const o = {name: 'jay}
isPlainObject(o) // true

// 例子2
const o = new Object()
o.name = 'jay'
isPlainObject(o)   // true

// 例子3
function C() {}
const c = new C()
isPlainObject(c);  // false

6.isUndefined(判定是否是undefined)

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

7.isFunction(判定是否是Function)

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

在vue3中该方法如下:

export const isFunction = (val: unknown) => typeof val === 'function'

两种方法比较:

  • typeof 操作符返回一个字符串,表示右侧操作数的类型。对于函数来说,会返回字符串 “function”。这种方式适用于各种函数,例如命名的函数,赋值到变量的函数,箭头函数等。(不过需要注意:部分浏览器(例如在 Chrome 57 )存在 bug,对于 HTML 的 object 元素和 embed 元素上运行 typeof 会返回 “function”。
  • toString() 方法检查一个变量的类型,它会获得变量的字符串表现形式,然后和字符串 ‘[object Function]’进行比对。不过这种方式不可靠,不能正确识别 复制到变量的函数、 ES 6 的 class 和异步函数。
  • 综合对比,优选typeof 方法判定function

测试代码如下:

// 1、普通function函数
let a = function(){console.log(1)};
console.log(typeof a);   // function
console.log(Object.prototype.toString.call(a)); // '[object Function]'

// 2、赋值到变量的函数
let b = function(){console.log(1)};
console.log(typeof b);  // function
console.log(Object.prototype.toString(b));  // '[object Object]'

// 3、ES6 class
class C{}
console.log(typeof C);  // function
console.log(Object.prototype.toString.call(C)); // '[object Object]'

8.isDate(判定是否是Date对象)

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

vue3中该方法如下:

export const isDate = (val: unknown) => val instanceof Date

两种方法对比:

  • 首先判定Date,不能使用~~typeof~~ ,因为会返回object
  • 我们通常创建一个Date对象,使用的是new Date(),通过new关键字创建的可以使用instanceofinstanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上)判定。同时toString方法也可以准确得到'[object Date]'
  • 综上所述,以上两种方法均可

9.isFile(判定是否是File文件对象)

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

10.isBlob(判定是否是Blob对象)

  • Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取。
function isBlob(val) {
  return toString.call(val) === '[object Blob]';
}

11.isBuffer(判定是否是Buffer对象)

  • JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
  • axios可以运行在浏览器和node环境中,所以内部会用到nodejs相关的知识
  • 在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用 Buffer.from() 接口去创建Buffer对象。
// 最终是通过Buffer.isBuffer()方法去判定
function isBuffer(val) {
  return val !== null             
  		&& !isUndefined(val)   // 先判断不是 `undefined`和`null`
  		&& val.constructor !== null 
  		&& !isUndefined(val.constructor)  // 再判断 `val`存在构造函数,因为`Buffer`本身是一个类
  		&& typeof val.constructor.isBuffer === 'function'  
  		&& val.constructor.isBuffer(val);  // 最后判定构造函数Buffer有`isBuffer`方法,并且用自身`isBuffer`判断
}

测试代码如下:

const buf = Buffer.from([1, 2, 3]);
console.log(typeof buf)  // object
console.log(buf instanceof Buffer);  // true
console.log(buf.constructor.isBuffer(buf))  // true

12.isArrayBuffer(判定是否是ArrayBuffer对象)

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

13.isFormData(判定是否是FormData对象)

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

测试代码:

let form = new FormData();
form.append('namme',12);
Object.prototype.toString.call(form)
'[object FormData]'

14.isStream(判定是否是Stream)

  • 这里isObjectisFunction为上文提到的方法。
  • 是对象,也是函数。就是流
function isStream(val) {
  return isObject(val) && isFunction(val.pipe);
}

15.isURLSearchParams(判定是否是URLSearchParams对象)

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

测试代码如下

const paramsString = "name=mj&age=13"
const searchParams = new URLSearchParams(paramsString);
console.log(isURLSearchParams(searchParams)) // true

三、其他常用的工具方法

1.trim(去除首尾空格)

  • trim方法不存在的话,用正则匹配
function trim(str) {
  return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
}

2.isStandardBrowserEnv(判定标准浏览器环境)

  • axios可运行在web worker、react-native中
  • 但是官方已经不推荐使用这个属性navigator.product。
/**
 *
 * 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
 *  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'
  );
}

3.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') {
    obj = [obj];
  }

  if (isArray(obj)) {
    // Iterate over array values。是数组,for循环执行回调fn
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    // Iterate over object keys。是对象,for in循环执行回调fn
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

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

5.extend(对象属性扩展)

  • 将一个对象的方法和属性扩展到另外一个对象上,并为对象方法指定上下文(this指向)
  • 遍历b,把b中所有属性赋值给a,并且若属性值为方法以及给出了上下文对象thisArg,则需要改变function的上下文对象。
function extend(a, b, thisArg) {
  forEach(b, function assignValue(val, key) {
  	// 判断传入了上下文对象,以及 b 中 属性值val 是方法,则需要绑定函数执行上下文对象
    if (thisArg && typeof val === 'function') {
      a[key] = bind(val, thisArg);  // 绑定函数的执行上下文对象
    } else {
    // 若并未传入上下文对象,或者不是函数,直接赋值
      a[key] = val;
    }
  });
  return a;
}

6.stripBOM(删除UTF-8编码中BOM)

  • BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode编码标准中用于标识文件是采用哪种格式的编码,但它对于文件的读者来说是不可见字符。
  • Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,即BOM.
  • UTF-8 是 Unicode 的实现方式之一。Unicode码4E25UTF-8编码是E4B8A5,两者是不一样的。它们之间的转换可以通过程序实现。
  • UTF-8是与字节顺序无关的,所以UTF-8编码文件通常要删除掉BOM
function stripBOM(content) {
  if (content.charCodeAt(0) === 0xFEFF) {
    content = content.slice(1);
  }
  return content;
}

总结

本文介绍了一些utils.js中的非常实用的工具函数;相信通过阅读源码,日积月累,并把这些代码或思想应用的自己项目中去,相信能够很好的提升自己的编码能力。

  • is开头的函数通常用来判断变量类型
  • 引用类型的数据通常用Object.prototype.toString.call(val)===’[object Array]'来判断
  • 基础数据类型,通常使用typeof去判断
  • instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

axios源码——工具函数utils.js 的相关文章

  • 使用JetPack4.2为NVIDIA Xavier刷机

    1 准备 Host xff1a Ubuntu 16 04或18 04系统 xff0c 配备鼠标 键盘 显示器 xff0c 联网 Xavier xff1a 配备鼠标 键盘 显示器 HDMI转VGA接口 xff08 连接显示器和Xavier x
  • Java与设备(PLC)通信

    通信名词 上位机 指可以直接发出操控命令的计算机 xff0c 一般是PC host computer master computer upper computer 控制者和提供服务者是上位机 xff1b 工控机 工作站 触摸屏可作为上位机
  • DAMA学习笔记

    第1章 数据管理 1 1 引言 1 数据管理 xff1a 为了实现数据价值 xff0c 制定计划 制度并执行 监督 2 数据管理专业人员 xff1a 技术人员 xff08 数据库管理员 网络管理员 程序员 xff09 和业务人员 xff08
  • 2023 学习日志

    2023 01 03 mybatis源码学习 学习视频 xff1a https www bilibili com video BV1Tp4y1X7FM p 61 1 amp vd source 61 cc82a52a9b9b8b31eca3
  • EL表达式两个foreach嵌套循环

    集合List中加List泛型的泛型 List lt RiskEvaSuitQuestion gt riskEvaSuitQuestionList 61 riskEvaSuitQuestionService getQueList 100003
  • JQuery通过radio,select改变隐藏显示div

    1 xff09 select下拉框控制div的隐藏与显示 lt script gt function checkYear var selectValue 61 34 select name 61 39 periodType 39 34 va
  • 开科唯识笔试

    对于这次的笔试 xff0c 我只想说BiShi 几道编程题加一道SQL题 1 找出所有三位数中的水仙花数 public void getNarcissusNums int g 61 0 s 61 0 b 61 0 sum 61 0 for
  • JDBC批量插入

    最近项目中有用到JDBC技术 xff0c 存在大量数据要进行插入 xff0c 通过研究采用批量插入速度快的不是一点点 下面简单比较了一下普通插入与批量插入5W条数据的时间效率 常规插入 xff1a 耗时12952ms public stat
  • 面试经历---YY欢聚时代(2015年11月21日上午初试、25日下午复试)

    YY欢聚时代一年多前去面试过一次 xff0c 当时鄙视了 xff0c 在现在的公司呆了1年半了 xff0c 感觉做得很不爽 xff0c 而且薪资又不满意 xff0c 所以想找个新工作 xff0c 就想去YY面试 下面将两次YY面试的经历写出
  • exe应用程序无法启动,因为应用程序的并行配置不正确

    问题 xff1a exe应用程序无法启动 xff0c 因为应用程序的并行配置不正确 有关详细信息 xff0c 请参阅应用程序事件日志 xff0c 或使用命令行 sxstrace exe 工具 原因查找 xff1a 1 xff09 开始 所有
  • TortoiseSVN is locked in another working copy

    TortoiseSVN提交报错 TortoiseSVN is locked in another working copy 原因 xff1a 可能是因为打开了多个commit会话 xff0c 然后又去修改了提交文件的内容 xff0c 导致文
  • Java对接企业微信

    最近需要对接企业微信 xff0c 例如将风险测评结果推送给企业微信中对应的用户 xff0c 然后用户对结果进行查看与确认操作 xff0c 所以这里就涉及到两方面 xff1a 1 xff09 将外部系统内容推送到企业微信 xff1b 2 xf
  • 微众银行面试

    机缘巧合 xff0c 其实并没有换工作的想法 xff0c 却收到了微众的面试邀请 xff0c 就想着去看看当是增长见识吧 xff0c 因为已经好久没准备面试的事情了 xff0c 而且微众毕竟作为腾讯系的看起来好像也不错 说实话那边离地铁站是
  • #TP4056#--3.7V锂电池充放电电路(实践日志篇)

    成就更好的自己 本篇为小型电源的实践日志 xff0c 内附各种充电应用电路 xff0c 并开源TP4056应用电路AD的原理图和PCB xff1b 先放一点锂电池常识性的知识 xff1a 锂电池是一类由锂金属或锂合金为负极材料 使用非水电解
  • ROS四旋翼无人机快速上手指南(1):无人机系统硬件概述与指南简介

    成就更好的自己 ROS无人机快速上手指南旨在于让使用此无人机开发平台的比赛参赛人员 xff0c 算法设计人员 xff0c 无人机爱好者更加快速的了解底层控制运作原理 xff0c 从而缩短开发周期 xff0c 减少掉坑次数 xff0c 快速验
  • ROS四旋翼无人机快速上手指南(2):Ubuntu18.04与ROS系统

    成就更好的自己 目录 Jetson版Ubuntu以及ROS的安装 xff1a ROS特性及Nano开发问题 PX4与Gazebo仿真环境 ROS与MATMAB仿真 Jetson版Ubuntu以及ROS的安装 xff1a ROS机器人系统运行
  • ROS四旋翼无人机快速上手指南(4):阿木实验室PX4功能包飞行控制分析与讲解(重点章节)

    成就更好的自己 这一章详细讲解一下阿木实验室 AMOV 的开源项目px4 command功能包 xff0c 此功能包通过mavlink协议直接控制烧录px4固件的自驾仪 xff0c 还融合了来自各个传感器的位姿 xff0c 距离等信息 xf
  • ROS四旋翼无人机快速上手指南(5):快速部署上层算法的操作与思路

    成就更好的自己 经过本系列上一篇文章关于PX4 command飞行控制功能包的分析 xff0c 相信大家对于飞整个流程有个大概的了解 xff0c 本章将在此基础上详细讲解一下应用级算法构建的思路与操作方法 关于PX4 command飞行控制
  • USB系列-LibUSB使用指南(1)-Windows下的报错与踩坑

    成就更好的自己 时隔一年再次开始撰写博客 xff0c 这一年的时间经历了很多 xff0c 现在终于稳定下来 以后很长一段时间都能够稳定的学习和更新 时间将会聚焦于USB和PCIe的开发进行 xff0c 能和大家共同进步真的很高兴 本篇为US
  • rosdep init和rosdep update出现问题解决,以及ros编程问题

    如果你在执行 rosdep init 过程中出现以下错误 ERROR cannot download default sources list from https raw githubusercontent com ros rosdist

随机推荐

  • linux内核体系结构

    本节介绍了linux内核的编制模式和体制结构 xff0c 然后详细描述linux内核代码目录中组织形式以及子目录各个代码文件的主要功能以及基本调用的层次关系 一个完整可用的操作系统主要由4部分组成 xff1a 硬件 操作系统内核 操作系统服
  • 基于OpenLTE的4G移动通信网络实验指导书

    基于本人本科毕业设计的成果 xff0c 设计了一套基于开源SDR项目 OpenLTE的实验指导书 xff0c 可以指引读者通过平台源码 平台提供的实验和结合实验对3GPP规范的解读分析来更直观 更多元立体的学习无线通信技术 xff0c 而不
  • 一行代码实现数组中数据频次值

    问题 xff1a 一行代码实现统计数组中每个name出现的次数 数组示例如下 xff1a 期望结果 xff1a 39 哈哈 39 2 39 哈哈1 39 1 39 哈哈2 39 2 span class token keyword var
  • mac bash_profile报错导致所有命令失效解决办法

    项目场景 xff1a 搭建flutter环境时 xff0c 在mac下需要配置环境变量 问题描述 xff1a 配置环境变量 xff0c 需要修改 bash profile文件 xff0c 修改文件保存退出后 发现文件有报错 xff0c 导致
  • 我理解的“大前端”

    前言 随着业务场景越来越复杂 xff0c 前端技术也越来越丰富 xff0c 这几年也迎来爆发期 xff0c 大前端 的概念逐渐涌现 本图根据本人理解整理 xff0c 如有不足 xff0c 欢迎指正 xff0c 感谢 一 终端 PC端 PC端
  • 前端获取用户地理定位的几种方式(Geolocation API,微信,腾讯地图)

    文章目录 前言一 Geolocation API二 微信 SDK1 引入jssdk2 获取签名 xff0c 注入配置3 调用JS SDK api 获取位置 三 第三方服务 xff08 腾讯地图服务 xff09 1 引入js文件2 获取定位
  • H5 软键盘自动搜索功能

    业务场景 xff1a 通常APP中的顶部搜索栏 xff0c 都配一个搜索按钮 同时输入文字软键盘弹起 xff0c 回车键自动变成搜索键 xff0c 点击软键盘中的搜索能进行搜索功能 xff0c 如下图taobao所示 xff1a 思考 软键
  • 基于vue-cli3构建自己的UI库

    文章目录 前言一 创建项目二 编写组件1 button组件2 引入字体图标icon文件3 引入Button组件看效果 三 修改目录结构1 packages文件夹2 打包修改2 demo展示 四 将UI库部署到npm上五 项目使用自己的UI库
  • vue3源码分析(三)—— 响应式系统(reactivity)

    系列文章目录 目录分析初始化流程响应式系统shared工具函数 文章目录 系列文章目录前言一 定义响应式数据1 reactive target 2 createReactiveObject2 1 入参2 2 响应式创建过程2 3 proxy
  • vue3源码分析(四)—— shared工具函数

    系列文章目录 目录分析初始化流程响应式系统shared工具函数 文章目录 系列文章目录前言1 数组中移除某元素2 字符串转数字3 转为字符串4 判定值是否发生改变5 判定数据类型5 1 数组5 2 Map5 3 Set5 4 Date5 5
  • 如何将两个rosbag包合并或者提取rosbag包中某些话题到一个rosbag里

    代码叫做merge bag py 运行的时候 python merge bag py v 1028msf bag msf bag vinReNoOutlier bag 就把msf bag和vinReNoOutlier bag完全合并在一起了
  • 解决 vscode中js变量 文件不能自动跳转问题~

    项目场景 xff1a 在项目开发中 xff0c 为了便于理解js代码逻辑和调试 xff0c 通常会使用快捷键自动定位到变量原始定义的文件位置 mac中快捷键 xff1a command 43 鼠标点击 但在vue项目开发中 xff0c 发现
  • vue3源码分析(二)—— 初始化流程

    系列文章目录 目录分析初始化流程响应式系统shared工具函数 文章目录 系列文章目录前言一 createApp在项目中的使用二 createApp源码追溯1 创建app实例1 1 ensureRenderer1 2 ensureRende
  • JS基础 ——解释执行

    文章目录 前言一 词法分析二 预编译创建全局作用域GO对象创建局部作用域AO对象 三 代码执行总结 前言 大家都知道 xff0c JS是一种不需要编译的解释型语言 但其实在浏览器执行JS代码前 xff0c 也有一个词法分析和预编译过程 xf
  • vue 项目中引入字体文件的正确方式~

    文章目录 前言一 开发中需要什么样的字体1 字体图标2 特殊字体 二 项目中引入字体文件1 字体文件2 css文件3 项目使用该字体 总结 前言 在UI设计稿中 xff0c 可能会有一些特殊字体 xff0c 或者是一些字体图标 对于特殊字体
  • vue3 使用 swiper轮播库

    文章目录 前言一 Swiper引入方式1 HTML标签引入方式2 CommonJs引入方式3 ES引入方式 xff08 采用 xff09 二 使用Swiper总结 前言 轮播图在前端开发中 xff0c 是常见需求 而Swiper库是最受前端
  • vue-cli2 老项目webpack3升级webpack5过程总结

    文章目录 背景一 webpack5环境要求二 升级步骤1 脚手架webpack cli2 升级webpack包3 更新webpack相关插件3 1 不推荐或被移除的插件3 2 升级babel到7版本3 3 更新插件 4 修改配置4 1 新增
  • 前端下载文件

    文章目录 前言二进制流前端核心实现下载功能有 xff1a 一 a标签 43 download属性二 window open url 34 blank 34 三 form表单四 接口请求 43 blob 43 a标签 43 download属
  • 前端JS 云打印 LODOP实践

    文章目录 前言一 Lodop是什么 xff1f 二 如何使用Lodop1 下载打印插件2 配置打印机3 html中植入打印控件4 调用Lodop对应的JS相关方法接口实现打印功能 三 Lodop主要方法接口三 注意点总结 前言 一般B S系
  • axios源码——工具函数utils.js

    文章目录 前言一 工具函数所在目录二 判定数据类型的函数1 isArray 判定数组 2 isString 判定字符串 3 isNumber 判定数值 4 isObject 判定对象 5 isPlainObject 判定纯对象 6 isUn