jQuery的无new构建
先看下一下初始想法
var aQuery = function(selector, context) {
//构造函数
}
aQuery.prototype = {
//原型
name:function(){},
age:function(){}
}
var a = new aQuery();
a.name();
由上可知,这样写会导致每个jQuery需要new一次,而真正的jQuery并不需要这样
所以这样尝试一下
var aQuery = function(selector, context) {
return new aQuery();
}
aQuery.prototype = {
name:function(){},
age:function(){}
}
虽然return 出来了一个实例,然而这次直接进入死循环了
在javascript中实例this只跟原型有关系
可以把jQuery类当作一个工厂方法来创建实例,把这个方法放到jQuery.prototye原型中。在原型中使用this指向构造函数,返回原型中构造出的新实例,解决了死循环问题
var aQuery = function(selector, context) {
return new aQuery.prototype.init();
}
aQuery.prototype = {
init: function() {
this.age = 18
return this;
},
name: function() {},
age: 20
}
但是构造函数变了,那绑定在aQuery上的公有属性和方法不都没了吗?(即aQuery.prototype.init.prototype为空)
由上可知,可以通过原型链解决这个问题。
var aQuery = function(selector, context) {
return new aQuery.prototype.init();
}
aQuery.prototype = {
init: function() {
return this;
},
name: function() {
return this.age
},
age: 20
}
aQuery.prototype.init.prototype = aQuery.prototype;
核心是jQuery.prototype.init.prototype = jQuery.prototype;
链式调用
代码可以采用链式调用,即$().show().hide();
想要使用链式调用,每个函数返回的结果必须是执行完毕后的对象。
aQuery.prototype = {
init: function() {
return this;
},
name: function() {
return this
}
}
插件接口
如果要为jQuery或者jQuery prototype添加属性方法,同样如果要提供给开发者对方法的扩展,从封装的角度讲是不是应该提供一个接口才对,字面就能看懂是对函数扩展,而不是看上去直接修改prototype.友好的用户接口
jQuery设置了jQuery.fn === jQuery.prototype
jQuery.extend = jQuery.fn.extend = function() {}
- jQuery.extend 调用的时候,this是指向jQuery对象的(jQuery是函数,也是对象),所以这里扩展在jQuery上。
- 而jQuery.fn.extend 调用的时候,this指向fn对象,jQuery.fn 和jQuery.prototype指向同一对象,扩展fn就是扩展jQuery.prototype原型对象。
- 这里增加的是原型方法,也就是对象方法了。所以jQuery的api中提供了以上2中扩展函数。