My Github

jQuery的XX如何实现?——1.框架

源码链接:内附实例代码

jQuery使用许久了,但是有一些API的实现实在想不通。于是抽空看了jQuery源码,现在把学习过程中发现的一些彩蛋介绍给大家(⊙0⊙)。

下面将使用简化的代码来介绍,主要关注jQuery的实现思想~>_<~

复制代码
 1 //匿名立即执行函数
 2 //1.防止污染全局空间
 3 //2.选择性保护内部变量
 4 (function(window, undefined){
 5     //第二参数undefined设置而不传的原因:
 6     // 外部发生这种情况:var undefined = 10时,undefined会被篡改
 7     // 设置第二参数而不传,则undefined就会被重置回原来值
 8 
 9     function jQuery(sel){
10         return new jQuery.prototype.init(sel);
11     }
12     
13     jQuery.prototype = {
14         constructor: jQuery,
15         init: function(sel){
16             if(typeof sel === 'string'){
17                 var that = this;
18                 //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代
19                 var nodeList = document.querySelectorAll(sel);
20                 Array.prototype.forEach.call(nodeList, function(val, i){
21                     that[i] = val;
22                 })
23                 this.selector = sel;
24                 this.length = nodeList.length;
25             }
26         }
27     }
28     
29     jQuery.prototype.init.prototype = jQuery.prototype;
30     
31     //对外暴露jQuery:将jQuery绑定在window上面
32     window.$ = jQuery;
33 })(window);
复制代码

 

--------------------------

jQuery一开始使用匿名立即执行函数包裹其内部,并在第5行对外暴露;

所谓的匿名立即执行函数即这个函数是匿名的(没有名字)、定义完后立即调用的;

当我们在外部调用$("div")时,其实调用的就是内部的jQuery("div");

(function(window, undefined){
  //内部变量
  
  //对外暴露jQuery:将jQuery绑定在window上面
  window.$ = jQuery;
})(window);

$("div")

 

--------------------------

好,接下来稍复杂点,下面的代码主要实现如图的互相引用:

以$('div')调用为例: 

从第2行代码可以看出,jQuery使用jQuery.prototype.init来实例化jQuery对象,但这会带来一个问题:

实例化的对象只能访问到init下的变量,而不能访问到jQuery.prototype(jQuery对外提供的API绑定在该对象下)。

于是乎,补写第21行代码,将init.prototype指向jQuery.prototype即可。

这样就完成了,使用init来实例化,且可以在init作用域下访问到jQuery.prototype。

复制代码
 1 function jQuery(sel){
 2     return new jQuery.prototype.init(sel);
 3 }
 4 
 5 jQuery.prototype = {
 6     constructor: jQuery,
 7     init: function(sel){
 8         if(typeof sel === 'string'){
 9             var that = this;
10             //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代
11             var nodeList = document.querySelectorAll(sel);
12             Array.prototype.forEach.call(nodeList, function(val, i){
13                 that[i] = val;
14             })
15             this.selector = sel;
16             this.length = nodeList.length;
17         }
18     }
19 }
20 
21 jQuery.prototype.init.prototype = jQuery.prototype;
复制代码

 为什么使用jQuery.prototype.init来实例化对象,而不直接使用jQuery函数呢?

假设使用jQuery函数来实例化对象,这样对象之间的引用的确可以简化为 jQuery-->jQuery.prototype。

但是调用会变得繁琐起来:new $('div'),所以基于这个考虑(猜测(⊙0⊙)),在内部使用较为复杂的实现,来简化调用。

--------------------------

好,最后,再来看一下init的实现。同样也简化了代码,只实现了最常用的一种情况。

jQuery会把获取到的nodeList处理成数组(方便后续使用),并在其下挂载一些变量,如length,selector。

复制代码
 1 init: function(sel){
 2     if(typeof sel === 'string'){
 3         var that = this;
 4         //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代
 5         var nodeList = document.querySelectorAll(sel);
 6         Array.prototype.forEach.call(nodeList, function(val, i){
 7             that[i] = val;
 8         })
 9         this.selector = sel;
10         this.length = nodeList.length;
11     }
12 }
复制代码

--------------------------

下一期预告:jQuery的XX如何实现?——2.show与链式调用

ps:代码已经上传到github中了

posted @   覃家辉  阅读(665)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示