extend: function() {
var C = function(E) {
for (var D in E) {
this[D] = E[D]
}
};
var e = Object.prototype.constructor;
return function(J, G, I) {
if (Ext.isObject(G)) {
I = G;
G = J;
J = I.constructor != e ? I.constructor: function() {
G.apply(this, arguments)
}
}
var E = function() {},
H,
D = G.prototype;
E.prototype = D;
H = J.prototype = new E();
H.constructor = J;
J.superclass = D;
if (D.constructor == e) {
D.constructor = G
}
J.override = function(F) {
Ext.override(J, F)
};
H.superclass = H.supr = (function() {
return D
});
H.override = C;
Ext.override(J, I);
J.extend = function(F) {
return Ext.extend(J, F)
};
return J
}
} ()
一、解读
function(J, G, I) {
if (Ext.isObject(G)) {
I = G;
G = J;
J = I.constructor != e ? I.constructor: function() {
G.apply(this, arguments)
}
}
var E = function() {},
H,
D = G.prototype;
E.prototype = D;
H = J.prototype = new E();
H.constructor = J;
J.superclass = D;
if (D.constructor == e) {
D.constructor = G
}
J.override = function(F) {
Ext.override(J, F)
};
H.superclass = H.supr = (function() {
return D
});
H.override = C;
Ext.override(J, I);
J.extend = function(F) {
return Ext.extend(J, F)
};
return J
}
在使用Ext自定义一个组件的时候,一般如下定义
Ext.extend(Ext.window,{});
或者是
Ext.extend(Ext.data.Connection, Ext.util.Observable, {})
当第二中国情况,跳过if语句,执行下边的语句,继承Ext.util.Observable.prototype上面的属性/方法,将{}里面的数据存放到 Connection.prototype上。
if (Ext.isObject(G)) {
I = G;
G = J;
J = I.constructor != e ? I.constructor: function() {
G.apply( this, arguments)
}
}
这一步我觉得最最关键的就是J=I.constructor这一部分,有什么用?如果我们没有自定义的constructor,那么 创建一个function(){G.apply(this,arguments)} ,这个就是继承后组件的构造函数,当用new创建对象的时候,都会调用这个方法,如果我们有自定义的constructor,那么就使用I.construtor当做继承后组件的构造方法
再说说这个function(){G.apply(this,arguments)方法,G.apply(this,arguments)会一层一层沿着继承的层次下去,直到访问到了其父构造函数(在Ext中也就是Ext.Component。),执行父构造函数里面的代码,这时父构造函数里面的this指的是,我们在外部new创建的那个对象(子),
好的,接下来,看一下
var E = function () {},
H,
D = G.prototype;
E.prototype = D;
H = J.prototype = new E();
刚开始,对这个中间方法,E非常不明白,为什么要使用这个方法,直接 H = J.prototype = G.prototype不就可以了吗? 它想要避免什么? 后面看了js的原型才明白,如果不使用中间方法,直接G.prototype 那么只要在J.prototype上做一些属性/方法的修改,会直接影响到G.prototype的原型。通过new E()的形式,就不会出现这些问题,同样可以继承G.prototype上的属性/方法
H.constructor = J;
J.superclass = D;
这里H.constructor = J; 什么意思? J.prototype继承的是G.prototype上的方法/属性,那么构造函数也是G上边的,所以这里我需要让J.prototype.constructor 指向J的本身。
J.superclass = D; 这里为什么要定义一个J上的静态方法? 有什么用?,用过Ext的人应该都看到过下面的用法
Ext.Window.superclass.initComponent.call(this);
这里Ext.Window.superclass指的就是D,也就是G.prototype,在G.prototype上有一个initComponent。这里有个比较有意思的地方,也如G.apply(this,arguments)一样,会一层一层的调用下去,如同递归一样,具体调用会在下面写个例子
if (D.constructor == e) {
D.constructor = G //形如D是{}形式,让他的constructor = {}
}
从代码上看D如果是{}的形式,也就是===Object.prototype.constructor,那么改成G.prototype.constructor = {} 对于{}类型的对象,他的prototype.constructor 是Fucntion Object(){},这里做这个修改应该是Ext某些地方需要,
J.override = function(F) { //定义override静态方法,通过J.override直接调用,不需要创建对象
Ext.override(J, F)
};
H.superclass = H.supr = ( function() {//上边J.superclass属性,这里是方法 superclass === supr
return D
});
H.override = C; //在J.prototype定义一个override可以通过new J 来调用
上边C表示的是作用域外部已经定义好的一个方法,有点像java里面类封装的味道
Ext.override(J, I); //在{}对象直接量上的内容放到J.prototype原型上面
J.extend = function(F) { //这个实现可以使用Ext.Panel.extend({})形式代替Ext.extend(Ext.Panel,{});
return Ext.extend(J, F)
};
第二部分:实例
Ext = {version: '1.0'}
Ext.extend = function(arg,obj) {
var temp = function() {arg.apply( this,arguments);} ;
var temp1 = function () {};
temp1.prototype = arg.prototype;
temp.prototype = new temp1();
temp.prototype.constructor = temp;
temp.superclass = arg.prototype;
for(var key in obj) {
temp.prototype[key] = obj[key];
}
return temp;
}
//测试
Ext.ftn1 = function(b) {
alert(b.name);
this.getName = function () {
alert('ftn1');
};
this.name = 'ftn1 by one' ;
this.init();
}
Ext.ftn1.prototype.init = function() {
}
Ext.ftn1.prototype.say = function() {
alert('my say');
}
Ext.ftn2 = Ext.extend(Ext.ftn1,{
init: function() {
Ext.ftn2.superclass.init.call(this);
this.name = '这是ftn2的name' ;
}
} );
Ext.ftn3 = Ext.extend(Ext.ftn2, {
init: function() {
Ext.ftn3.superclass.init.call(this); //这里superclass是extend中的arg.prototype
this.name = "这是ftn3的name" ;
}
} );
Ext.ftn4 = Ext.extend(Ext.ftn3, {
init: function() {
Ext.ftn4.superclass.init.call(this); //这里使用call是为了让ftn4继承ftn3的init中的this.name属性
this.name = "这是ftn4的name" ;
}
} );
var fn4 = new Ext.ftn4({name:'stray'} ,{ age:'111'} );
alert(fn4.name);
这个是我写的一个例子,和Extend源码大同小异。
第一步,我们看一下Ext.ftn1,按照java的角度理解,这个是一个基类,我需要从这个基类去扩展ftn2
Ext.ftn2 = Ext.extend(Ext.ftn1,{
init: function() {
Ext.ftn2.superclass.init.call(this);
this.name = '这是ftn2的name' ;
}
} );
通过第一步的分析,我们知道在Extend 创建了一个function
function () {
ftn1.apply( this,arguments);
}
这个就是第一部分代码中J, Ext.ftn2 引用的就是这个J.
Ext.ftn3 = function() {
ftn2.apply(this,argumets);
}
Ext.ftn4 = function() {
ftn3.apply(this,arguments);
}
Ext.ftn3 = function() {
ftn2.apply(this,arguments) //这时候这里的this就是fn4这个对象
}
ftn2.apply(this,arguments)就会调用
Ext.ftn2 = function() {
ftn1.apply(this,arguments);
}
ftn1.apply(this,arguments)就会执行
Ext.ftn1 = function(b) {
alert(b.name);
this.getName = function () {
alert('ftn1');
};
this.name = 'ftn1 by one' ;
this.init();
}
init: function() {
Ext.ftn4.superclass.init.call(this); //这里使用call是为了让ftn4继承ftn3的init中的this.name属性
this.name = "这是ftn4的name" ;
}
init: function() {
Ext.ftn3.superclass.init.call(this); //这里superclass是extend中的arg.prototype
this.name = "这是ftn3的name" ;
}
Ext.ftn1 = function(b) {
alert(b.name);
this.getName = function () {
alert('ftn1');
};
this.name = 'ftn1 by one' ;
this.init();
}