jquery用的不是很多,但是对于jquery这种飘逸的书写风格憧憬已久,三个月前去看过jquery源码,无果,把javascript高级程序设计又看了两遍,再来分析分析jquery源码。也不知道正确与否。
jquery设计的整体框架:
$ = jquery = function(){};
首先肯定是这样的,定义jquery和$两个全局变量,对应着一个function。
jquery是原型扩展函数库,所以肯定有以下:
jquery.fn = jquery.prototype = function(){};
为什么要让fn=prototype呢,想必就是作者为了减少书写难道,以及封装接口,其实原理还是在原型对象中进行扩展。
到这里,有人要问,jquery最关键的$()返回jquery对象时怎么实现的呢?要我肯定这么写~
$ = jquery = function(){
if(!(this == jquery)) {
return new jquery;
}
};
这样的确可以实现$()返回jquery对象,但是有一个问题就是,此时jquery = function(){}中的属性就会覆盖原型中的属性,jquery作为一个原型扩展的库,是不希望这样的。
eg :
$ = jquery = function(){
this.length = 1;
if(!(this == jquery)) {
return new jquery;
}
};
jquery.fn = jquery.prototype = function(){
length:2,
getLength:function(){return this.length;}
};
var test = $().getLength();//1
我们希望结果是2,就是我们希望我们所取到的都是原型对象中的属性,怎么办呢,搞个指针指向原型嘛,this最适合干这种事情了(什么,直接返回原型对象就行了?那样写着也太奇怪了吧,构造函数返回自己的原型对象,多别扭啊,我们看看jquery准备怎么做呢):
$ = jquery = function(){
this.length = 1;
return jquery.fn.init();
};
jquery.fn = jquery.prototype = function(){
init:function(){
return this;
},
length:2,
getLength:function(){return this.length;}
};
var test = $().getLength();//2
问题解决了,this指向jquery.prototype了,所以
$().getLength();
结果是2.
细心的看官应该发现了,现在还有问题:从设计上init作为一个初始化函数,中间肯定会有别的属性吧,这些属性和下面的属性冲突了怎么办,都调用一个this明显破坏了作用域的独立性:如:
$ = jquery = function(){
return jquery.fn.init();
};
jquery.fn = jquery.prototype = function(){
init:function(){
this.length = 1;
return this;
},
length:2,
getLength:function(){return this.length;}
};
var test = $().getLength();//1
完了,我们想要返回原型,又想要作用域独立出来,怎么办呢怎么办,一步一步来,先把this独立出来。
$ = jquery = function(){
return new jquery.fn.init();
};
ok,现在this分出去了,this只能取到init里面的属性,但是,又拿不到prototype里面其他属性了。
jquery用了一个很巧妙但是又很诡异的写法,
jquery.fn.init.prototype = jquery.fn;
好了,现在一切问题都解决了,通过原型链,我们可以通过$()返回init作用域,init的原型对象又指向jquery的原型对象,所以可以沿着原型链找到jquery原型中的对象。
很费劲啊~~~~~总之,我们初步实现了大体的框架:
$ = jquery = function(){
return new jquery.fn.init();
};
jquery.fn = jquery.prototype = function(){
init:function(){
this.length = 1;
return this;
},
length:2,
getLength:function(){return this.length;}
};
jquery.fn.init.prototype = jquery.fn;
以后我们的扩展函数就写在jquery.fn里面,我们的选择器就写在init里面。
所以我们可以在源码里面看到:
jquery.extend = jquery.prototype.extend = function(obj){//这里的实现就是一个添加过程~};
我们通过对象传进函数给extend,extend就把函数加在jquery原型中,就可以用$().xxx来使用了。
再看看我们之前说的init,里面要准备选择器呀,这也是jquery一个核心。
累了- -
下篇文章再说说我对选择器的理解。
本来觉得挺明白的写起来应该能够描述得清除,但是发现还是一塌糊涂,总之不管你明不明白,我自己是能够看明白了= =
我写博客就是为了自己以后翻阅的时候能够想起来就行,所以就~,真有看官看不懂再私聊我吧 哈哈