html
<div id="aa"></div>
<div id="bb"></div>
js
/*
//链模式
//var A = function(){};A.prototype = {sk:function(){...}};
//一般想调用对象里的方法,可以new A().sk()
//但A.sk()或A().sk()都不行
//前者sk绑定在A的原型而非A,后者是A的执行结果没有返回值所以找不到sk
//可以找人帮忙
var A = function(){
return B;
}
var B = A.prototype = {
kk: 2,
sk: function(){
return this.kk;
}
}
A().sk(); //访问sk
//jquery中,为了减少变量创建,直接把B看做A的一个属性
var A = function(){
return A.fn;
}
A.fn = A.prototype = {
//...
};
但在jQ中是为了返回元素,这里返回的是A.fn对象。所以需要增加一个获取元素的init方法
var A = function(selector){
return A.fn.init(selector);
}
A.fn = A.prototype = {
init: function(selector){
return document.getElementById(selector);
},
kk: 2,
sk: function(){
return this.kk;
}
};
console.log(A('aa')); //<div id="aa"></div>*/
/*
//但这样无法获取sk等其他方法
//而init中this指向的就是A.fn,返回this即可
//但这样就无法获取元素
//不过既然this指向的是对象,那么就可以设置属性,设置为数组,并增加length属性
var A = function(selector){
return A.fn.init(selector);
//return new A.fn.init(selector);
}
A.fn = A.prototype = {
init: function(selector){
this[0] = document.getElementById(selector);
this.length = 1; //为对象增加length属性
return this;
},
kk: 2,
sk: function(){
return this.kk;
}
};
console.log(A('aa')); //Object{0:div#aa, init:function, kk: 2, length: 1, sk: function}
//console.log(A('bb')); //若放开这条,会把上面的输出结果也覆盖为#bb
//因为每次返回的A.fn.init(selector)都指向同一对象
//只要把 return A.fn.init(selector); 改为 return new A.fn.init(selector); 即可
//但这时返回的对象没有sk等方法属性,无法使用
//因为A.fn.init(selector)的this返回的是当前对象,即A.fn和A.prototype
//而new后this指向的是A.fn.A.init
//因为new A.fn.init(selector)的构造函数是A.fn.init或A.init(从A.prototype找到)
//即A.fn.init=A.init,把A.init带入A.fn.init的init中可得A.fn.A.init
//而jQ中_proto_原型指向的不是A.fn.A.init,而是jQuery[0]
//因为jQ中加了A.fn.init.prototype = A.fn;*/
//为此A可以改为
var A = function(selector){
return new A.fn.init(selector);
}
A.fn = A.prototype = {
//强化构造器
constructor: A,
init: function(selector){
this[0] = document.getElementById(selector);
this.length = 1; //为对象增加length属性
return this;
},
kk: 2,
sk: function(){
return this.kk;
},
//这时输出的还是{}的对象类型,
//而jQ输出的是类似数组的jQ对象类型
//只需要增加下面3行代码,即可输出这种形式
//增强数组
//好像只要加splice也可以
//一个 Javascript 对象,只要定义了 length 属性和 splice 方法,它看起来就像一个数组
//即使splice: function(){}也可以
push:[].push,
sort:[].sort,
splice:[].splice
};
A.fn.init.prototype = A.fn;
console.log(A('aa'));
//此时_proto_指向A,且可以正常使用其他方法
//另外像取类名等也可以循环this[i]=...
//扩展对象
A.extend = A.fn.extend = function(){
//第一个参数为源对象,后面的是扩展对象
var i = 1,
len = arguments.length,
target = arguments[0],
j;
//如果只有一个参数
if(i == len){
//源对象为当前对象
target = this;
i--;
}
for(; i < len; i++){
for(j in arguments[i]){
target[j] = arguments[i][j];
}
}
return target;
}
//扩展A
A.extend(A, {ds: 123456});
//或var eDemo = A.extend({ds: 123456});
console.log(A.ds);
//扩展A.fn
A.fn.extend({dss: 124});
//或A.extend(A.fn, {get: function(){...; return this;}});
//return this是为了链式调用
林秀栋的技术博客