最近花了一些时间看了一下jQuery的源码,以下部分是我对源码的核心部分进行的提取。这样能更清晰的看清jQuery本身的结构,接下来对这段核心的代码进行详细的分析。只限于对目前对jQuery的理解层次。
1.首先jQuery同样被包裹在一个匿名块里面,接着对这个匿名块进行了调用,
并且传递的参数为window,可能还包括undefined,在这部分暂不做分析。
之所以传递window进入到匿名块中,是为了接下来核心代码形成的闭包,
减少了对作用域链层次的查询。这样在jQuery的内部中访问window会更快些。
2.接下来定义一个匿名函数并对其进行调用,这个匿名函数有一个返回值就是jQuery对象
随后将返回值(jQuery对象)赋值给变量jQuery(代码的3行和23行)。
注意:这个函数只会执行一次,这是jQuery设计巧妙地方之一。
最后在window上定义两个属性$和jQuery,其值也就是刚刚通过匿名函数的返回值jQuery。
这也是一般库的做法,这样$和jQuery就会存在于全局上下文的变量对象中。在程序的任何地方都可以访问到。
3.代码中(5-22行)才是真正的jQuery对象的核心。在jQuery匿名块的内部定义了一个构造函数名字也叫jQuery。
所有的jQuery对象都是通过这个构造方法构造的。这个方法非常简单,接收一个参数也就是选择器的名字,new一个
jQuery.fn.init对象并且返回。这样我们就会得到一个符合当前选择器的jQuery对象。
4.代码中(9-18行)是jQuery的原型,一切的巧妙设计都在这里。
首先抛去jQuery.fn不看,那这很简单就是jQuery构造函数的原型。constructor有指回了jQuery的构造函数。
原型里面有一个方法init,两个属性length、splice。那这几个东西到底有什么用呢?
首先init方法其实就是根据我们提供的选择器进行DOM查询最终并返回的过程,这里暂不细讲。
当一个ECMA对象拥有length、splice两个属性时,这个对象就会成为一个数组,因为ECMA中数组也是对象。
好,在处理完jQuery构造函数的原型后,又在jQuery构造函数(对象)上定义了一个属性fn也就是jQuery.fn。
最后将jQuery构造函数的原型的引用赋值给了jQuery.fn,这其实是对原型的一次缓存,以免以后频繁使用原型。
方便实现插件机制。
5.进行到现在你可能会发现一个问题,为什么每次调用jQuery无论选择器是什么,都会得到一些相同的方法呢?
也就是说当使用$('#demo')时,首先给jQuery的构造函数传递'#demo',然后new一个jQuery.fn.init也就是
jQuery构造函数原型里面的方法,最后得到一个DOM对象的引用,但这时这个对象是不具备length、splice属性的
也就是说不具备其它jQuery方法的。--当然这里我没有写。到底是什么原因改变了这一切使其具备了呢?
代码(20行)jQuery构造函数的原型的引用又赋值给了init的原型,这样通过init函数new出来的对象也就具备了
jQuery构造函数的原型上的所有属性。这真是一种巧妙的设计。
总结:
好了现在总结一下整个jQuery实现的流程,比如当我们使用$('#demo')时,会进入jQuery的构造方法,但是并没用
通过这个方法去new一个实例。而是通过new一个jQuery构造函数原型里面的init构造方法的实例,这个方法做了一件事
就是查找DOM元素并返回。而通过将jQuery构造函数的原型的引用赋值给这个init构造函数的原型。是这个刚刚构造出来
的这个实例拥有所有的jQuery属性、方法。那么,每次根据选择器调用jQuery的时候,都只是查找并返回一个实例而已,
而其属性和方法早已通过原型机制获得了。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。