前言
你好,我是若川。这是
学习源码整体架构第一篇。整体架构这词语好像有点大,姑且就算是源码整体结构吧,主要就是学习是代码整体结构,不深究其他不是主线的具体函数的实现。本篇文章学习的是打包整合后的代码,不是实际仓库中的拆分的代码。
学习源码整体架构系列文章如下:
1.学习 jQuery 源码整体架构,打造属于自己的 js 类库
2.学习 underscore 源码整体架构,打造属于自己的函数式编程类库
3.学习 lodash 源码整体架构,打造属于自己的函数式编程类库
4.学习 sentry 源码整体架构,打造属于自己的前端异常监控SDK
感兴趣的读者可以点击阅读。
虽然现在基本不怎么使用jQuery了,但jQuery流行10多年的JS库,还是有必要学习它的源码的。也可以学着打造属于自己的js类库,求职面试时可以增色不少。
本文章学习的是v3.4.1版本。unpkg.com源码地址:https://unpkg.com/jquery@3.4.1/dist/jquery.js
自执行匿名函数
1 | 复制代码(function(global, factory){ |
外界访问不到里面的变量和函数,里面可以访问到外界的变量,但里面定义了自己的变量,则不会访问外界的变量。
匿名函数将代码包裹在里面,防止与其他代码冲突和污染全局环境。
关于自执行函数不是很了解的读者可以参看这篇文章。
[译] JavaScript:立即执行函数表达式(IIFE)
浏览器环境下,最后把$ 和 jQuery函数挂载到window上,所以在外界就可以访问到$和jQuery了。
1 | 复制代码if ( !noGlobal ) { |
支持多种环境下使用 比如 commonjs、amd规范
commonjs 规范支持
commonjs实现 主要代表 nodejs
1 | 复制代码// global是全局变量,factory 是函数 |
amd 规范 主要代表 requirejs
1 | 复制代码if ( typeof define === "function" && define.amd ) { |
cmd 规范 主要代表 seajs
很遗憾,jQuery源码里没有暴露对seajs的支持。但网上也有一些方案。这里就不具体提了。毕竟现在基本不用seajs了。
无 new 构造
实际上也是可以 new的,因为jQuery是函数。而且和不用new效果是一样的。
new显示返回对象,所以和直接调用jQuery函数作用效果是一样的。
如果对new操作符具体做了什么不明白。可以参看我之前写的文章。
源码:
1 | 复制代码 var |
1 | 复制代码jQuery.fn === jQuery.prototype; // true |
关于这个笔者画了一张jQuery原型关系图,所谓一图胜千言。
1 | 复制代码<sciprt src="https://unpkg.com/jquery@3.4.1/dist/jquery.js"> |
Vue源码中,也跟jQuery类似,执行的是Vue.prototype._init方法。
1 | 复制代码function Vue (options) { |
核心函数之一 extend
用法:
1 | 复制代码jQuery.extend( target [, object1 ] [, objectN ] ) Returns: Object |
jQuery.extend API
jQuery.fn.extend API
看几个例子:
(例子可以我放到在线编辑代码的jQuery.extend例子codepen了,可以直接运行)。
1 | 复制代码// 1. jQuery.extend( target) |
结论:extend函数既可以实现给jQuery函数可以实现浅拷贝、也可以实现深拷贝。可以给jQuery上添加静态方法和属性,也可以像jQuery.fn(也就是jQuery.prototype)上添加属性和方法,这个功能归功于this,jQuery.extend调用时this指向是jQuery,jQuery.fn.extend调用时this指向则是jQuery.fn。
浅拷贝实现
知道这些,其实实现浅拷贝还是比较容易的:
1 | 复制代码// 浅拷贝实现 |
深拷贝则主要是在以下这段代码做判断。可能是数组和对象引用类型的值,做判断。
1 | 复制代码if ( copy !== undefined ) { |
为了方便读者调试,代码同样放在jQuery.extend浅拷贝代码实现codepen,可在线运行。
深拷贝实现
1 | 复制代码$.extend = function(){ |
为了方便读者调试,这段代码同样放在jQuery.extend深拷贝代码实现codepen,可在线运行。
深拷贝衍生的函数 isFunction
判断参数是否是函数。
1 | 复制代码var isFunction = function isFunction( obj ) { |
深拷贝衍生的函数 jQuery.isPlainObject
jQuery.isPlainObject(obj)
测试对象是否是纯粹的对象(通过 “{}” 或者 “new Object” 创建的)。
1 | 复制代码jQuery.isPlainObject({}) // true |
1 | 复制代码var getProto = Object.getPrototypeOf; |
extend函数,也可以自己删掉写一写,算是jQuery中一个比较核心的函数了。而且用途广泛,可以内部使用也可以,外部使用扩展 插件等。
链式调用
jQuery能够链式调用是因为一些函数执行结束后 return this。
比如jQuery 源码中的addClass、removeClass、toggleClass。
1 | 复制代码jQuery.fn.extend({ |
jQuery.noConflict 很多js库都会有的防冲突函数
用法:
1 | 复制代码 <script> |
jQuery.noConflict 源码
1 | 复制代码var |
总结
全文主要通过浅析了jQuery整体结构,自执行匿名函数、无new构造、支持多种规范(如commonjs、amd规范)、核心函数之extend、链式调用、jQuery.noConflict等方面。
重新梳理下文中学习的源码结构。
1 | 复制代码// 源码结构 |
可以学习到jQuery巧妙的设计和架构,为自己所用,打造属于自己的js类库。
相关代码和资源放置在github blog中,需要的读者可以自取。
下一篇文章是学习underscorejs的源码整体架构。学习 underscore 源码整体架构,打造属于自己的函数式编程类库
读者发现有不妥或可改善之处,欢迎评论指出。另外觉得写得不错,可以点赞、评论、转发,也是对笔者的一种支持。
笔者往期文章
前端使用puppeteer 爬虫生成《React.js 小书》PDF并合并
扩展阅读
chokcoco: jQuery- v1.10.2 源码解读
chokcoco:【深入浅出jQuery】源码浅析–整体架构
笔者另一个系列
关于
作者:常以若川为名混迹于江湖。前端路上 | PPT爱好者 | 所知甚少,唯善学。
若川的博客,使用vuepress重构了,阅读体验可能更好些
掘金专栏,欢迎关注~
segmentfault前端视野专栏,欢迎关注~
语雀前端视野专栏,新增语雀专栏,欢迎关注~
知乎前端视野专栏,欢迎关注~
github blog,相关源码和资源都放在这里,求个star^_^~
欢迎加微信交流 微信公众号
可能比较有趣的微信公众号,长按扫码关注。欢迎加笔者微信ruochuan12(注明来源,基本来者不拒),拉您进【前端视野交流群】,长期交流学习~
若川视野
本文使用 mdnice 排版
本文转载自: 掘金