上面两节中,已经大概剖析了jq的基本框架。然后,还有jq一相当重要的功能没有提及,那就是jq的扩展功能。
Jq一共有两种扩展功能,一种是类的静态扩展,一种是类实例的扩展。
但其实在jq中,两个都是统一使用一个函数的。先来看下一段代码:
(function(){
var test=function(selector){
return new test.prototype.init(selector);
}
test.prototype={
init:function(selector){
this.elem=document.getElementById(selector);
return this;
},
name:function(){
alert(123)
return this;
},
pwd:function(){
alert(456)
},
hide:function(){
this.elem.setAttribute('style','display:none;');
return this;
},
getAttribute:function(){
return this.elem.getAttribute('style');
}
}
test.extend=test.prototype.extend=function(op){
for (var name in op) {
this[name]=op[name]
}
}
test.prototype.init.prototype=test.prototype;
$=test;
}())
这样,我们同样也可以使用两种方法对我们上面那个框架进行扩展了。
使用方法是:
$.prototype.extend({
h:function(){
alert(3)
}
});
$('t').h();
这是类实例的扩展,还有一种是类静态的扩展:
$.extend({
h:function(){
alert(1)
}
});
$.h();
在jq中,对类实例的扩展是使用$.fn.extend(),我们只要js中加上:
test.fn=test.prototype就可以了。
这里,为什么不使用
test.extend=function(op){
test.prototype=op;
}
这是因为test.prototype=op会将原先原型中的方法和属性删除掉,替换成op;
但是又为什么不使用:
test.extend=function(op){
for(var name in op) {
eval("test.prototype."+name+"=op."+name)
}
}
这是因为如果这样添加后,要调用h()这个方法,便不能使用$.h(),而是需要使用$.protype.h()
因为$只是一个函数,其this指针指向window。
在这里还涉及到一个知识点,那就是访问某个实例的时候,会进行两次搜索,第一次是搜索改实例本身,第二次搜索是搜索this指针指向的对象的protype中的属性和方法。
像$.h(),其this指针是指向window的,因此第二次搜索的是window中的原型,而不是test中的原型。
但如果是:
test.extend=function(op){
this.prototype=op;
}
这样也不可取,因为这样的话,任何对象都可以调用我们的h()方法,因为this指针是指向window的。
因此,最可取的,还是早先我们那种实现方法,即可正确运行,有加快速度(在第一次搜索中就能调用).
注意:new 某个函数()后,实际上将其this指针指向window改而指向函数实例本身的。