参考http://www.cnblogs.com/aaronjs/p/3278578.html
##构造
jQuery的构造函数是直接返回了jQuery.prototype.init()函数的实例,为什么不是直接返回一个this呢,有人说是为了省略一个new,那如果返回this,但是不用new会怎么样呢,$()
的时候会得到window,所以这种说法有道理,但是我觉得还不止这点,我觉得还有更深层的原因在,不过目前我还不知道(口罩),下面我们假装已经知道了不能直接返回this,而是要返回一个new好的对象
那么肯定不能new jQuery这样写,这样写就引用自己了,所以就写在了jQuery.prototype.init里
这种是源码里的
var jQuery = function(selector, context) {
return new jQuery.prototype.init();
}
jQuery.prototype = {
init: function() {
return this;
},
getAge: function() {
return this.age
},
age: 20
}
//注意这句
jQuery.prototype.init.prototype = jQuery.prototype;
下面这种和上面的区别在于没有在jQuery的构造函数里用new,也没有最后一句原型的赋值,看一下这种方式的问题
var jQuery = function(selector, context) {
return jQuery.prototype.init();//区别在这里
}
jQuery.prototype = {
init:function(){
return this;
}
getAge: function(){
return this.age
},
age: 20
}
自己测试一下可以发现,这种形式创建出来的实例,它的this是指向jQuery.prototype的,这个就有点不合理,按说创建出来的实例this怎么也得指向jQuery才是,同样的,如果在构造函数里返回一个别的对象,也会有这个问题(压根就不是jQuery的实例了)
要修正这个问题,要用new,下面这种和第一种只差最后那一句原型赋值了,看一下下面这种的问题
var jQuery = function(selector, context) {
return new jQuery.prototype.init();
}
jQuery.prototype = {
init: function() {
this.age = 18
return this;
},
getAge: function() {
return this.age
},
age: 20
}
因为new操作相当于是创建一个Object的实例o,又把o的原型赋值为构造函数的原型(这里是jQuery.prototype.init函数的原型),然后把构造函数的属性赋值给o,所以这里的实例创建出来,可以发现没有getAge属性,也就是没有jQuery.prototype的属性,因为这里的实例创建出来是用的jQuery.prototype.init函数的原型
所以第一种形式最后这一句就是干这个的,把jQuery.prototype赋值给jQuery.prototype.init函数的原型
注意上面的讨论都是基于jQuery的实例创建形式都是直接var a = $(...)
这样的
##扩展接口
jQuery.extend 对jQuery本身的属性和方法进行了扩展
jQuery.fn.extend 对jQuery.fn的属性和方法进行了扩展
jQuery.extend = jQuery.fn.extend = function() {
...
}
jQuery.extend 调用的时候,this是指向jQuery,所以扩展在jQuery上。
而jQuery.fn.extend 调用的时候,this指向fn对象,jQuery.fn 和jQuery.prototype指向同一对象,扩展fn就是扩展jQuery.prototype原型对象。
这种写法感觉比较神奇,自己感觉目前的水平是写不出,记录一下
感觉框架里很多代码都是在做健壮性兼容性的活,很重要但是容易影响我这种低水平的看核心功能的实现