您的位置:首页 > 编程语言

Ext.extend 用法以及代码解读

2010-03-11 16:37 295 查看

概述

Ext.extend

Ext
的继承机制,这个函数的代码相当难懂。要明白这个函数的代码,首先要知道这个函数如何使用。

使用方式

使用示例

假设有个
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
(
"f1 in base"
);

   
}

 

   
this

.
f2
=
function

()
{

       
alert
(
"f2 in base"
);

   
}

}

 

ChildClass
=
function

()
{

 
ChildClass
.
superclass
.
constructor
.
call
(
this

);

}
      

 

Ext
.
extend
(
ChildClass
,
BaseClass
,
{

   
f1
:
function

()
{

       
alert
(
"f1 in child"
);

   
},

 

   
f3
:
function

()
{

       
alert
(
"f3 in child"
);

   
}

});

 

var

b
=
new

ChildClass
();

b
.
f1
();

b
.
f2
();

b
.
f3
();

 

可以去执行一下,可以发现
f1
的执行结果仍然是
"f1 in base"
。并没有真正的达到
override
的效果。

 

Ext.extend puts the properties
specified in the 3rd argument into the
subclass's
prototype

 

也就是说:第三个参数里面的函数被放置在了子类的
prototype
中。

而在
ChildClass.superclass.constructor.call(this);
这句上,
BaseClass

f1
成了
ChildClass
的变量,而不是
ChildClass.prototype
。通过对
JavaScript
的原型继承的了解,可以知道,实例变量的优先级是高于
prototype
的,所以上面的这个代码是
达不到
override
的功能的。

 

修改的方式如下:

BaseClass
=
function

()
{

};

 

BaseClass
.
prototype
=
{

   
f1
:
function

()
{

       
alert
(
"f1 in base"
);

   
}

};

 

代码解读

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
(){

   
// inline overrides

   
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
(){

   
// inline overrides

   
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
(){

   
// inline overrides

   
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
(){

   
// inline overrides

   
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
中省略掉了。原因在于我尝试了多次,发现参数为两个参数的时候,只有第一个参数为
Object
对象或者为
3
个参数的时候,第二个参数为
Object
才会进入此段代码。

但是发现
superFn
也时
function
Object(){}
,在
IE

FF
下都是如此。那么我就不是很清楚这段代码
到底是什么用的了,若有清楚的,告诉一声,哈。

 

上面的有几段代码源自网络,若有版权侵犯,非常抱歉。

 

From : http://www.blogjava.net/dragonshrimp/archive/2008/03/01/183060.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐