详解Extextend的使用方法.docx
- 文档编号:3971327
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:13
- 大小:18.96KB
详解Extextend的使用方法.docx
《详解Extextend的使用方法.docx》由会员分享,可在线阅读,更多相关《详解Extextend的使用方法.docx(13页珍藏版)》请在冰点文库上搜索。
详解Extextend的使用方法
extend (Objectsubclass,Objectsuperclass,[Objectoverrides]:
Object
第一个参数:
子类
第二个参数:
父类
第三个参数:
要覆盖的属性。
这里需要强调一下,子类继承下来的是父类中通过superclass.prototype方式定义的属性(包括用此方法定义的函数)。
使用方式
使用示例
假设有个 function 名为 SuperClass ,要实现一个子类,名为 MyClass 。
下面的两种方式都可以实现这个功能。
MyClass = Ext . extend ( SuperClass , { /**/ });
Ext . extend ( MyClass , SuperClass , { /**/ });
下面来个具体示例:
var a = function ( id ){
this . id = id ;
}
a . prototype = {
tostring :
function (){
return this . id ;
}
};
b = function ( id ){
b . superclass . constructor . call ( this , id );
}
Ext . extend ( b , a , {
tostring :
function (){
return String . format ( "b:
{0}" , this . id );
}
});
// 测试一下
var obj1 = new a ( "obj1" );
alert ( obj1 . tostring ());
var obj2 = new b ( "obj2" );
alert ( obj2 . tostring ());
或者下面的代码,可以得到同样的效果:
var a = function ( id ){
this . id = id ;
}
a . prototype = {
tostring :
function (){
return this . id ;
}
};
b = Ext . extend ( a , {
tostring :
function (){
return String . format ( "b:
{0}" , this . id );
}
});
// 测试一下
var obj1 = new a ( "obj1" );
alert ( obj1 . tostring ());
var obj2 = new b ( "obj2" );
alert ( obj2 . tostring ());
一个错误例子
下面看个示例:
BaseClass = function () {
this . f1 = function () {
alert ( "f1inbase" );
}
this . f2 = function () {
alert ( "f2inbase" );
}
}
ChildClass = function () {
ChildClass . superclass . constructor . call ( this );
}
Ext . extend ( ChildClass , BaseClass , {
f1 :
function () {
alert ( "f1inchild" );
},
f3 :
function () {
alert ( "f3inchild" );
}
});
var b = new ChildClass ();
b . f1 ();
b . f2 ();
b . f3 ();
可以去执行一下,可以发现 f1 的执行结果仍然是 "f1inbase" 。
并没有真正的达到 override 的效果。
Ext.extendputsthepropertiesspecifiedinthe3rdargumentintothe subclass's prototype
也就是说:
第三个参数里面的函数被放置在了子类的 prototype 中。
而在 ChildClass.superclass.constructor.call(this); 这句上, BaseClass 的 f1 成了 ChildClass 的变量,而不是 ChildClass.prototype 。
通过对 JavaScript 的原型继承的了解,可以知道,实例变量的优先级是高于 prototype 的,所以上面的这个代码是达不到 override 的功能的。
修改的方式如下:
BaseClass = function () {
};
BaseClass . prototype = {
f1 :
function () {
alert ( "f1inbase" );
}
};
代码解读
JavaScript 中的继承实现
先了解一下最简单的继承是如何实现的:
function Extend ( subFn , superFn ){
subFn . prototype = new superFn ()
subFn . prototype . constructor = subFn
}
function Animal (){
this . say1 = function (){
alert ( "Animal" );
}
}
function Tiger (){
this . say2 = function (){
alert ( "Tiger" );
}
}
Extend ( Tiger , Animal );
var tiger = new Tiger ();
tiger.say1();// "Animal"
tiger.say2();// "Tiger"
可以看到最简单的继承只做了两件事情,一是把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn . prototype . constructor 为 subFn 。
Ext.extend 的代码
Ext.extend 函数中用到了 Ext.override ,这个函数把第二个参数中的所有对象复制到第一个对象的 prototype 中。
首先贴上 Ext.override 函数的代码:
Ext . override = function ( origclass , overrides ){
if ( overrides ){
var p = origclass . prototype ;
for ( var method in overrides ){
p [ method ] = overrides [ method ];
}
}
}
然后贴上 Ext.extend 的代码:
/**
* 继承,并由传递的值决定是否覆盖原对象的属性
* 返回的对象中也增加了 override() 函数,用于覆盖实例的成员
* @param { Object } subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象)
* @param { Object } superclass 父类,被继承
* @param { Object } overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖
* @method extend
*/
function extend (){
//inlineoverrides
var io = function ( o ){
for ( var m in o ){
this [ m ] = o [ m ];
}
};
return function ( sb , sp , overrides ){
if ( typeof sp == 'object' ){
overrides = sp ;
sp = sb ;
sb = function (){ sp . apply ( this , arguments );};
}
var F = function (){}, sbp , spp = sp . prototype ;
F . prototype = spp ;
sbp = sb . prototype = new F ();
sbp . constructor = sb ;
sb . superclass = spp ;
if ( spp . constructor == Object . prototype . constructor ){
spp . constructor = sp ;
}
sb . override = function ( o ){
Ext . override ( sb , o );
};
sbp . override = io ;
Ext . override ( sb , overrides );
return sb ;
};
}();
代码中进行了太多的简写,看起来不是特别方便,把代码中的简写补全,代码如下:
function extend (){
//inlineoverrides
var inlineOverride = function ( o ){
for ( var m in o ) {
this [ m ] = o [ m ];
}
};
return function ( subFn , superFn , overrides ){
if ( typeof superFn == 'object' ) {
// 如果 subFn 也是对象的话(一般来说 subFn 这里放的是父类的构造函数),那么第三个参数 overrides 参数相当于被忽略掉
overrides = superFn ;
superFn = subFn ;
//subFn 重新定义了函数
subFn = function (){
superFn . apply ( this , arguments );
};
}
var F = function (){
}, subFnPrototype , superFnPrototype = superFn . prototype ;
F . prototype = superFnPrototype ;
subFnPrototype = subFn . prototype = new F ();
subFnPrototype . constructor = subFn ;
subFn . superclass = superFnPrototype ;
if ( superFnPrototype . constructor == Object . prototype . constructor ) {
superFnPrototype . constructor = superFn ;
}
subFn . override = function ( obj ){
Ext . override ( subFn , obj );
};
subFnPrototype . override = inlineOverride ;
Ext . override ( subFn , overrides );
return subFn ;
};
};
补全以后也不是特别容易明白,那么我们就把这个代码分开,分为 2 个参数和 3 个参数。
两个参数的 Ext.extend 代码
首先把代码改写成两个参数的。
// 两个参数的时候的代码,注意第二个参数必须为 object
function extend (){
//inlineoverrides
var inlineOverride = function ( o ){
for ( var m in o ) {
this [ m ] = o [ m ];
}
};
return function ( superFn , overrides ){
var subFn = function (){
superFn . apply ( this , arguments );
};
var F = function (){
}, subFnPrototype , superFnPrototype = superFn . prototype ;
F . prototype = superFnPrototype ;
// 注意下面两句就是上面最简单的继承实现。
subFnPrototype = subFn . prototype = new F ();
subFnPrototype . constructor = subFn ;
// 添加了 superclass 属性指向 superFn 的 Prototype
subFn . superclass = superFnPrototype ;
// 为 subFn 和 subFnPrototype 添加 override 函数
subFn . override = function ( obj ){
Ext . override ( subFn , obj );
};
subFnPrototype . override = inlineOverride ;
// 覆盖掉子类 prototype 中的属性
Ext . override ( subFn , overrides );
return subFn ;
};
};
从注释中可以看到,做的工作很简单,只是定义一个 subFn 函数,这个函数中会调用 superFn 函数。
定义了 subFn 以后,就使用上面的最简单的继承方式实现继承。
然后为 subFn 和 subFn 的 prototype 添加了一个 override 函数。
最后的 Ext.override(subFn,overrides); 把 overrides 中的函数写入 subFn 的 prototype 中。
三个参数的 Ext.extend 代码
下面我们把函数改写为只处理 3 个参数的,改写后的代码如下:
// 三个参数时的代码
function extend (){
//inlineoverrides
var inlineOverride = function ( o ){
for ( var m in o ) {
this [ m ] = o [ m ];
}
};
return function ( subFn , superFn , overrides ){
var F = function (){
}, subFnPrototype , superFnPrototype = superFn . prototype ;
F . prototype = superFnPrototype ;
// 注意下面两句就是上面最简单的继承实现。
subFnPrototype = subFn . prototype = new F ();
subFnPrototype . constructor = subFn ;
// 添加了 superclass 属性指向 superFn 的 Prototype
subFn . superclass = superFnPrototype ;
// 为 subFn 和 subFnPrototype 添加 override 函数
subFn . override = function ( obj ){
Ext . override ( subFn , obj );
};
subFnPrototype . override = inlineOverride ;
// 覆盖掉子类 prototype 中的属性
Ext . override ( subFn , overrides );
return subFn ;
};
};
过程与两个参数的时候相差无几,只是两个参数的时候, subFn 时重新定义的一个 function ,而三个参数的时候,这个步骤就省略了。
总结及说明
这样大家就对这个函数很明白了吧,也可以知道 Ext.extend 的继承只会覆写构造函数 prototype 中的对象,使用的时候需要多加注意。
注意下面一段代码:
if ( superFnPrototype . constructor == Object . prototype . constructor) {
superFnPrototype . constructor = superFn ;
}
详解Ext.extend的使用方法
这段代码我在改写的 Ext.extend 中省略掉了。
原因在于我尝试了多次,发现参数为两个参数的时候,只有第一个参数为 Object 对象或者为 3 个参数的时候,第二个参数为 Object 才会进入此段代码。
但是发现 superFn 也时 functionObject(){} ,在 IE 和 FF 下都是如此。
那么我就不是很清楚这段代码到底是什么用的了,若有清楚的,告诉一声,哈
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详解 Extextend 使用方法