淄博网站建设程序,淘宝网站内搜索引擎优化怎么做,网络推广营销软件,东莞阳光网论坛大家好#xff0c;我是若川。最近组织了源码共读活动#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与#xff0c;每周大家一起学习200行左右的源码#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。本文来自读者Ethan01投稿… 大家好我是若川。最近组织了源码共读活动感兴趣的可以点此加我微信 ruochuan12 参与每周大家一起学习200行左右的源码共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。本文来自读者Ethan01投稿写了axios源码中的工具函数~非常值得一学。原文链接https://juejin.cn/post/70426106798152417581.前言歌德说过读一本好书就是在和高尚的人谈话。同理读优秀的开源项目的源码就是在和牛逼的大佬交流。之前总觉得阅读源码是一件了不起的事情是只有大佬才会去做的事。其实源码也不是想象的那么难至少有很多看得懂。 比如源码中的工具函数就算是初级的前端开发也是能够看懂的。重要的是要迈出这一步阅读源码没什么的。阅读本文你将学到1、javascript、nodejs调试技巧及调试工具
2、如何学习调试axios源码
3、如何学习优秀开源项目的代码应用到自己的项目
4、axios源码中实用的工具函数2.环境准备2.1 读开源项目的贡献指南打开 axios[1] , 你会惊奇的发现这不是在浏览器中打开了一个vscode吗你没有看错确实是在浏览器中打开了vscode,而且还打开了axios的源码。如果你仔细看了浏览器地址栏里的url, 你会发现github后多了1s,顾名思义就是1s打开github上的项目。一个小扩展在每一个github项目中的url里直接加上1s,就能在网页版vscode中查看源码了不过貌似现在只能查看不能调试调试的话还是要把源码clone到本地。开源项目一般能在根目录下的README.md文件或CONTRIBUTING.md中找到贡献指南。贡献指南中说明了参与贡献代码的一些注意事项比如代码风格、代码提交注释格式、开发、调试等。打开CONTRIBUTING.md[2]可以看到在54行的内容Running sandbox in browserbash
$ npm start
# Open 127.0.0.1:3000这里就是告诉我们在如何在浏览器中运行项目的。2.2 克隆项目并运行这里使用axios的版本是v0.24.0;git clone https://github.com/axios/axios.gitcd axiosnpm start打开 http://localhost:3000/这时候可以看到这么一个页面image.png打开浏览器的控制台选中source选项然后在axios目录中可以找到源码如下图image.png这个axios.js就是入口文件这时候就可以随意打断点进行调试了。其实阅读所有源码的流程都类似之所以说的这么详细是为了能够让没有阅读过源码的同学也能够跟着一步一步的阅读起来。当你读完之后肯定会有不少的收获把这个过程和收获记录下来慢慢的提升自己早晚会成为大佬。3. 工具函数今天的主角是utils.js[3]文件, 以下列出了文件中的工具函数3.1 isArray 判断数组var toString Object.prototype.toString;// 可以通过 toString() 来获取每个对象的类型
// 一般返回值是 Boolean 类型的函数命名都以 is 开头
function isArray(val) {return toString.call(val) [object Array];
}3.2 isUndefined 判断Undefined// 直接用typeof判断
// 注意 typeof null object
function isUndefined(val) {return typeof val undefined;
}3.3 isBuffer 判断 buffer// 先判断不是 undefined和null
// 再判断 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);
}什么是Buffer?JavaScript 语言自身只有字符串数据类型没有二进制数据类型。但在处理像TCP流或文件流时必须使用到二进制数据。因此在 Node.js中定义了一个Buffer 类该类用来创建一个专门存放二进制数据的缓存区。详细可以看 官方文档[4] 或 更通俗易懂的解释[5]。因为axios可以运行在浏览器和node环境中所以内部会用到nodejs相关的知识。3.4 isFormData 判断FormData// instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上function isFormData(val) {return (typeof FormData ! undefined) (val instanceof FormData);
}// instanceof 用法function C() {}
function D() {}const c new C()c instanceof C // output: true 因为 Object.getPrototypeOf(c) C.prototypec instanceof Object // output: true 因为 Object.prototype.isPrototypeOf(c)c instanceof D // output: false 因为 D.prototype 不在 c 的原型链上3.5 isObject 判断对象// 排除 null的情况
function isObject(val) {return val ! null typeof val object;
}3.6 isPlainObject 判断 纯对象纯对象用{}或new Object()创建的对象。function isPlainObject(val) {if (Object.prototype.toString.call(val) ! [object Object]) {return false;}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// 其实就是判断目标对象的原型是不是null 或 Object.prototype3.7 isDate 判断Datefunction isDate(val) {return Object.prototype.toString.call(val) [object Date];
}3.8 isFile 判断文件类型function isFile(val) {return Object.prototype.toString.call(val) [object File];
}3.9 isBlob 判断Blobfunction isBlob(val) {return Object.prototype.toString.call(val) [object Blob];
}Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取。3.10 isFunction 判断函数function isFunction(val) {return Object.prototype.toString.call(val) [object Function];
}3.11 isStream 判断是否是流// 这里isObject、isFunction为上文提到的方法
function isStream(val) {return isObject(val) isFunction(val.pipe);
}3.12 isURLSearchParams 判断URLSearchParamsfunction isURLSearchParams(val) {return typeof URLSearchParams ! undefined val instanceof URLSearchParams;
}// 例子
const paramsString qURLUtils.searchParamstopicapi
const searchParams new URLSearchParams(paramsString);
isURLSearchParams(searchParams) // trueURLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串详情可看 MDN[6]var paramsString qURLUtils.searchParamstopicapi
var searchParams new URLSearchParams(paramsString);for (let p of searchParams) {console.log(p);
}// 输出
[ q, URLUtils.searchParams ]
[ topic, api ]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(); // qURLUtils.searchParamstopicapitopicwebdev
searchParams.set(topic, More webdev);
searchParams.toString(); // qURLUtils.searchParamstopicMorewebdev
searchParams.delete(topic);
searchParams.toString(); // qURLUtils.searchParams3.13 trim 去除首尾空格// trim方法不存在的话用正则
function trim(str) {return str.trim ? str.trim() : str.replace(/^\s|\s$/g, );
}3.14 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);
}但是官方已经不推荐使用这个属性navigator.product。image.png3.15 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.* 如果是数组回调将会调用value, index, 和整个数组** If obj is an Object callback will be called passing* the value, key, and complete object for each property.* 如果是对象回调将会调用value, key, 和整个对象** param {Object|Array} obj The object to iterate* param {Function} fn The callback to invoke for each item*/function forEach(obj, fn) {// Dont 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循环执行回调fnfor (var i 0, l obj.length; i l; i) {fn.call(null, obj[i], i, obj);}} else {// Iterate over object keys// 是对象for循环执行回调fnfor (var key in obj) {// 只遍历可枚举属性if (Object.prototype.hasOwnProperty.call(obj, key)) {fn.call(null, obj[key], key, obj);}}}
}所以源码为什么不用forEach和for...in...呢3.16 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的话这个好处就荡然无存了。4.总结本文主要介绍了axios源码的调试过程以及介绍了一些utils.js中的非常实用的工具函数相信通过阅读源码日积月累并把这些代码或思想应用的自己项目中去相信能够很好的提升自己的编码能力。come on! worker!同时也推荐一些好用的工具浏览器中运行vscode, 查看源码[7]代码沙盒能运行多种语言且可以添加依赖[8]vs code 的 code Runner插件[9]参考资料[1]axios: https://github1s.com/axios/axios[2]CONTRIBUTING.md: https://github1s.com/axios/axios/blob/HEAD/CONTRIBUTING.md[3]utils.js: https://github.com/axios/axios/blob/master/lib/utils.js[4]官方文档: http://nodejs.cn/api/buffer.html#buffer[5]更通俗易懂的解释: https://www.runoob.com/nodejs/nodejs-buffer.html[6]MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams[7]浏览器中运行vscode, 查看源码: https://github1s.com/axios/axios[8]代码沙盒能运行多种语言且可以添加依赖: https://codesandbox.io/[9]vs code 的 code Runner插件: https://marketplace.visualstudio.com/items?itemNameformulahendry.code-runner················· 若川简介 ·················你好我是若川毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇在知乎、掘金收获超百万阅读。从2014年起每年都会写一篇年度总结已经写了7篇点击查看年度总结。同时最近组织了源码共读活动帮助3000前端人学会看源码。公众号愿景帮助5年内前端人走向前列。识别上方二维码加我微信、拉你进源码共读群今日话题略。分享、收藏、点赞、在看我的文章就是对我最大的支持