为了深入学习下jQuery,最近打算看看源码,刚开始看这个我内心其实是拒绝的。。。第一印象就是好难理解,没办法硬骨头总是要去啃得,看了好多分析源码的文章博客,第一篇当然是Aaron的jQuery源码解读系列的开篇之整体架构。介绍的还是比较详细的,推荐~当然要抱着怀疑的眼光去看,不一定人家写的就是对的,敲出来验证下才是王道,这篇文章后的评论也可以看看,是大家对于该文章某些地方的质疑。
看完这篇文章其实我是半懂的状态,后来又看到一篇总结的博文,大概是在此基础上总结的。
我并不想重复的记录下相同的文字,只是想说一下我理解的时候觉得困难的地方。
先附上源码:
123456789101112 | jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery );},jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { ... return this; } ...}jQuery.fn.init.prototype = jQuery.fn; |
1.jQuery
中为什么要返回new jQuery.fn.init
首先为了让我们在调用jQuery的时候像这样:
12 | $('#id').css();$.ajax(); |
就是把jQuery看成是一个类,在原型上绑定方法就相当于成员方法,在jQuery上绑定工具方法,相当于类的静态方法,实例化之后就能直接调用这些方法了。
那要怎样才能返回一个实例呢,对 最容易想到的就是return new jQuery();
写完有没有发现什么不对的地方,var jQuery = function(selector, context) { return new jQuery();}
这个方法陷入了死循环了。然后就把方法放到原型中去
123456789101112 | jQuery = function( selector, context ) { return jQuery.fn.init();},jQuery.fn = jQuery.prototype = { init: function() { this.name='Tom'; return this; }, anotherName:'Mike'};console.log(jQuery().anotherName);//"Mike"console.log(jQuery().name);//"Tom" |
这样返回实例对象是解决了,但是this原本只指向jQuery类的,这里却指向了jQuery.fn;所以需要隔离出作用域出来。故返回的是new jQuery.fn.init();
但是这个时候,jQuery并不能调用jQuery.fn上的方法了。所以才有了这一句:jQuery.fn.init.prototype = jQuery.fn;
将init的原型指向jQuery.fn,也就是用jQuery的原型对象覆盖init的原型对象,因为JQ对象根本就是init函数的实例对象,console.log(jQuery() instanceof jQuery.prototype.init); //true
;这样一来,jQuery就能调用jQuery.fn上的属性和方法了。
2.为什么为了避免全局污染的时候要传入第二个参数undefined
在参数列表中给出undefined
,但是不传入值,那么就确保了函数内部undefined
是自身的值。在ECMAScript5之前undefined
都是可写的,也就是undefined
可以赋值的。jQuery作者这么做的目的还有防止程序员对undefined
进行赋值后使得代码出现了不可预料的bug。
以上就是个人结合各方博客对于初识源码中难点的理解,有不对的请指出,不胜感激~
附上两篇博文的链接:
http://www.cnblogs.com/aaronjs/p/3278578.html
http://www.cnblogs.com/SheilaSun/p/4779895.html
原文:大专栏 初识jQuery源码