jQuery为开发者提供了快速便捷的DOM操作, 那么如果我们想添加自己的方法到jQuery原型或者构造函数上, 我们该怎么做呢? jQuery暴露出了extendAPI来解决这个问题, 这篇文章就来观摩一下其拓展机制.
一、更新
[2019-4-21]
Changed
- 改进文章格式🎉
二、前置
2.1 深拷贝vs浅拷贝
PS: 关于
深、浅拷贝的知识, 网上的各种博客已经层出不穷了, 对其实现方式以及基本原理都讲解的很清楚. 这里还是苦口婆心地提一下, 它们的主要区别, 也是为了接下来地阅读作个铺垫吧.
那么, 问题来了:
Q: 两者的
主要区别是什么?
- 对于
数组, 两者是一样的功能 - 对于
键值对对象shallowCopy只拷贝Object.keys(), 也就是第一层键值deepCopy则反之
一个简单的例子:
1 | const obj = { |
关于它们的区别, 还可以参考我之前的文章:
PS: 前端基础重拾系列之——深浅拷贝
三、用法
3.1 jQuery.extend&jQuery.fn.extend
jq提供了两种方式, 供我们自定义拓展:
- jQuery.extend(…)
- 拓展
Static, 也就是静态方法
- 拓展
- jQuery.fn.extend(…)
- 拓展
Non-static(实例方法)
- 拓展
3.2 如何使用?
分析拓展机制前, 先做一件事情, 那就是如何去使用它, 俗话说知其意,悟其理,守其则,践其行, 了解了它是如何使用, 再去深究其原理, 这也是我写文章的一贯原则.
PS: 自己用
jQuery很少, 所以对extendAPI也基本没用过, 但是这并不影响对其理解, 毕竟知识是相通的, 所谓的框架只不过是换了身皮.
一般来说, 开发者可以根据可以传递的参数个数不同, 通过下述三种方式使用(以jQuery.fn.extend)为例:
3.2.1 使用方式一
PS: 给jq原型添加方法. jQuery的各种
plugin就是通过如此来挂载
1 | $.fn.extend({ |
还有另一种方式, 那就是通过直接赋值的方式来拓展:
1 | $.fn['sayHello'] = function() { |
3.2.2 使用方式二
PS: 合并
后续对象到首个对象, 纯粹返回一个拓展后的对象, 此时与jQuery没有任何关系.
1 | const origin = {}; |
3.2.3 使用方式三
PS: 是否执行深层的
copy操作.
1 | const origin = {}; |
四、细说
PS: 对于内部的全部代码逻辑, 我觉得并没有必要细看, 所以这里只选取了一种情况————
单个参数, 也就是对于拓展jQuery原型or静态方法的处理.
4.1 贴源码
先来贴一下部分源码:
1 | jQuery.extend = jQuery.fn.extend = function() { |
4.2 析源码
对于单个参数的处理逻辑很简单:
- 将
target赋值为this, this有两种情况- jQuery构造函数
- jQuery实例
for-in遍历options- 给
target赋值- 过滤掉
target的值为undefined的情况
- 过滤掉
五、总结
jQuery提供的extend极大地方便了开发者, 同样的, var框架同样有对应的拓展方法, 这里就不说了(其实是太菜了).
当然, 最近也在挤时间看react源码, 感觉其复杂度高了几个层级, 所以还是一步一步地走下去吧!
五、示例代码
使用ts重构了我之前写的jQuery类库, 项目地址戳这里