1、對(duì)象的繼承
在prototype.js中extend實(shí)現(xiàn)中,只是簡(jiǎn)單的屬性拷貝。
在dojo
的lang.js中,也有個(gè)屬性拷貝的函數(shù) 叫 dojo.lang.mixin。顯然dojo的實(shí)現(xiàn)嚴(yán)謹(jǐn)多了。
既沒有改變Object.prototype,另外toString函數(shù)也可以拷貝到目標(biāo)對(duì)象中。? 如果你熟悉
commons-beanutils
的copyProperties方法,那么就好理解了,但要注意javascript中function函數(shù)也是數(shù)據(jù)類型。
?
dojo.lang.mixin?
=
?function(obj,?props)
{

?var?tobj?
=
?
{}
;

?
for
(var?x?in?props)
{

??
if
(typeof?tobj[x]?
==
?
"
undefined
"
?
||
?tobj[x]?
!=
?props[x])?
{
???obj[x]?
=
?props[x];
??}
?}
?
//
?IE?doesn't?recognize?custom?toStrings?in?for..in
?
if
(dojo.render.html.ie?
&&
?dojo.lang.isFunction(props[
"
toString
"
])?
&&
?props[
"
toString
"
]?
!=
?obj[
"
toString
"
])?
{
??obj.toString?
=
?props.toString;
?}
?
return
?obj;
}
?
例子代碼
<SCRIPT LANGUAGE="JavaScript">
<!--
function pf(key,msg){
??? document.writeln("<div>"+key+':'+msg+"</div>");
}
Object.extend = function(destination, source) {
? for (property in source) {
??? destination[property] = source[property];
? }
? return destination;
}
function Source(name){
??? this.name=name;
};
Source.prototype.getName=function(){
??? return this.name;
}
Source.prototype.obj={name:'aaa'};
Source.prototype.toString=function(){
??? return this.name;
}
var source=new Source('zkj');
var obj={};
pf('obj.name',obj.name)
Object.extend(obj,source);
pf('obj.name',obj.name)//zkj
pf('source',source)//zkj
pf('obj',obj)//沒有拷貝toString函數(shù)
pf('source.obj.name',source.obj.name)//aaa
obj.obj.name='bbb';
pf('obj.obj.name',obj.obj.name) //bbb
pf('source.obj.name',source.obj.name)
//-->
</SCRIPT>
對(duì)象之間的屬性拷貝(extend) 和java c++中繼承概念完全不一樣。有幾個(gè)問題需要注意
a、如果源對(duì)象的屬性在 (for in) 不出現(xiàn),那目標(biāo)對(duì)象將不全。? for in
b、如果源對(duì)象的屬性是prototype的屬性,也可以拷貝,但目標(biāo)對(duì)象將當(dāng)作自己的屬性來使用。
c、如果屬性是對(duì)象(引用傳遞),那任何持有者修改這個(gè)對(duì)象,內(nèi)容全部都修改了。所以只是“淺度clone”.你也可以模仿dwr? DWRUtil.toDescriptiveString方法實(shí)現(xiàn)多層的屬性拷貝(沒必要吧)。
d、如果屬性是方法,那目標(biāo)對(duì)象使用方法可能會(huì)出現(xiàn)問題,因?yàn)榉椒ㄖ泻芸赡馨?this 關(guān)鍵字。所以我覺得javascript對(duì)象只當(dāng)作數(shù)據(jù)模型使用可能會(huì)簡(jiǎn)單很多。如DWR框架,這也是我喜歡dwr原因之一,完全以數(shù)據(jù)為核心的AJAX框架。
2、自定義類的繼承
我把用function定義的類叫自定義類。如 function Person(name){this.name=name}; 這種類有個(gè)復(fù)雜的原型對(duì)象porotype。
如
果用prototype.js實(shí)現(xiàn)這類的繼承,只能變相的通過原型對(duì)象的拷貝來實(shí)現(xiàn)。(Object.extend(des.prototype,
source.prototype))。這樣兩個(gè)類的原型對(duì)象內(nèi)容一樣,但這種方法叫繼承太過牽強(qiáng),我感覺用起來有一定限制。(大家可以讀
prototype.js看到這種用法)
關(guān)于類的繼承我推薦dojo或犀牛書中寫法。
<SCRIPT LANGUAGE="JavaScript">
var dojo={};
dojo.lang={};
dojo.inherits = function(subclass, superclass){
?subclass.prototype = new superclass();
?subclass.prototype.constructor = subclass;
?subclass.superclass = superclass.prototype;
}
dojo.lang.mixin = function(obj, props){
?var tobj = {};
?for(var x in props){
??if(typeof tobj[x] == "undefined" || tobj[x] != props[x]) {
???obj[x] = props[x];
??}
?}
?// IE doesn't recognize custom toStrings in for..in
?if(true) {
??obj.toString = props.toString;
?}
?return obj;
}
dojo.lang.extend = function(ctor, props){
?this.mixin(ctor.prototype, props);
}
dojo.lang.extendPrototype = function(obj, props){
?this.extend(obj.constructor, props);
}
function Person(){
}
Person.prototype.getName=function(){
??? return this.name;
}
Person.prototype.setName=function(name){
??? this.name=name;
}
Person.prototype.toString=function(){
??? return this.name;
}
function Man(){
}
dojo.inherits(Man, Person);
dojo.lang.extend(Man,{
getName:function(){return this.name+' of Man';},
getAge:function(){return this.age;},
setAge:function(age){this.age=age;}
});
var man=new Man();
man.setName('zkj');
man.setAge(25);
alert(man.getName());
alert(man.getAge());
alert(Man.superclass.getName.call(man,null));//父方法
</SCRIPT>
這樣模擬的java中的繼承,也有方法覆蓋等概念,可對(duì)于javascript語言來說,這樣造成一定的復(fù)雜性。有幾個(gè)方面需要注意:
a、在java中,繼承是為了代碼重用,語言的特性決定java繼承是有用的(多用接口代替繼承)。但javascript中,繼承存在好象沒那么必要,估計(jì)是那幫java迷的杰作。
b、javascript語言的可重用代碼比較難寫,不同瀏覽器,語言版本也帶來一些復(fù)雜性。javascript包機(jī)制,模塊劃分,嚴(yán)格的語法檢查等等的不完善支持,造成javascript代碼的一片混亂。
c、javascript在網(wǎng)頁中的作用與java,c++作用不同,實(shí)現(xiàn)的功能決定高級(jí)語言特征不需要。但現(xiàn)在ajax的興起可能有改觀。
d、繼承雖然可以模擬實(shí)現(xiàn),但這只是模擬,并不是語言底層支持,在代碼質(zhì)量、代碼風(fēng)格、可讀性、可維護(hù)性都會(huì)造成一定麻煩。如果你用了dojo,那你必須讓讀你代碼的人也熟悉dojo。或知道你的代碼實(shí)現(xiàn)思路。
e、IDE支持。javascrit極大的軟肋,就不多說。javascript框架的復(fù)雜度、推廣的難度,編譯檢查等,決定javascript的復(fù)雜應(yīng)用只是少數(shù)人能干的事。
f、
瀏覽器中javascript需要多線程嗎?好象csdn見有人模擬了個(gè)實(shí)現(xiàn)。完全不需要。瀏覽器下載了代碼,自己用自己的。所以我認(rèn)為
javascript中只有靜態(tài) (static)方法就夠了,沒必要有對(duì)象概念。只要var obj=new
Object();這種只放數(shù)據(jù)的對(duì)象加上靜態(tài)方法就夠了。
大家可以看看dojo的代碼。
說這么多,在你自己寫的代碼中,你不要用javascript的類繼承,我寧愿ctrl+c\v 也不用繼承來重用代碼。除非dojo真的能統(tǒng)一江湖。
參考:
?? <javascript權(quán)威指南>
???javascript的一些文章
?? prototype.js
?? dojo的文檔
?
?