你的位置:首页 > Java教程

[Java教程]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中了