?? b、javascript預(yù)定義的對(duì)象。Function Array Date?? RegExp? Error等對(duì)象。這些對(duì)象使用比較簡(jiǎn)單,也不討論了。
?? c、用new Object()創(chuàng)建的對(duì)象。等同與var o={a:0,b:'s'};
?? d、用自定義的構(gòu)造函數(shù)創(chuàng)建的對(duì)象。function O(){};? var o=new O();
?? e、dom模型定義的構(gòu)造函數(shù),瀏覽器為你創(chuàng)建的對(duì)象。用var o=document.getElementById();或其他方法獲得。
?? f、null也是對(duì)象。typeof(null)= object.undefined我理解為變量預(yù)編譯的初始化值,而null是特殊的對(duì)象。如果一個(gè)變量=null,說明這個(gè)變量是個(gè)對(duì)象,但不是我上面提到的任何來源方式的對(duì)象。 如document.getElementById(頁面中不存在的id);可以產(chǎn)生一個(gè)null對(duì)象。
?? 用typeof()? 方法返回的是 object 的變量都是對(duì)象。 Function除外用new定義的不一定都是對(duì)象.























































看以上兩段代碼,估計(jì)很多人對(duì)后面的代碼熟悉,也這樣寫了。可他們執(zhí)行結(jié)果是一樣的。如果你改變了javascript對(duì)象的原型對(duì)象后會(huì)有些區(qū)別。
在這我想提出以下幾個(gè)問題:
??? a、javascript對(duì)象也是單根繼承的對(duì)象.但不是所有對(duì)象都繼承自O(shè)bject.如例子中的Date對(duì)象。
??? b、千萬別亂定義Object.prototype原型對(duì)象。prototype.js中加了個(gè)extends被人說了半天。但我們自己寫類庫時(shí),千萬別嘗試改Object的prototype。
??? c、別用javacript語言模仿java來寫代碼。想上面的,需要一個(gè)person的“類”,并不是非需要定義一個(gè),注意javascript對(duì)象的屬性是可以隨意增加或刪除的。并不象java那樣在類中寫死。
??? d、就上面兩段代碼有什么區(qū)別呢?可以簡(jiǎn)單的說是person繼承了Object”類“。javascript中對(duì)象的繼承是用prototype來實(shí)現(xiàn)的,后面我們討論prototype原型對(duì)象。
??? e、那我們應(yīng)用的時(shí)候到底是否該自己定義自己的構(gòu)造函數(shù)(如person),還是直接使用Object呢?這是個(gè)復(fù)雜的問題,我個(gè)人來說喜歡多用Object.
開始之前我先明確個(gè)問題。如下代碼






















見如下代碼:
























我理解function返回的數(shù)據(jù)類型是和Object同等級(jí)的數(shù)據(jù)類型。它有Object實(shí)例(new Object())的一些特性,但它不是Object的實(shí)例,因?yàn)樗鼪]有繼承Object.prototype.toString=function(){return 'myToString'};但我們Person.toString=function(){return 'Person toString'};改變了覆蓋了方法。
在《javascript權(quán)威指南》中,作者用這個(gè)特性實(shí)現(xiàn)了“類方法、類變量”static方法,與java中不同,這些方法不能用new Person()來調(diào)用。
Object?????????????????? function???????????? 同等級(jí) function可以定義屬性,可以(for in)
new Object()??????? new function()??? 同等級(jí) new function()繼承了Object的prototype, ?????????????????????????????????????????????????????也會(huì)繼承 function的prototype
小例子。看了原型對(duì)象就很清楚了啊。 原型對(duì)象最好在代碼最前面定義,很容易被覆蓋啊!






































原型對(duì)象prototype是Object或與之同等級(jí)的對(duì)象如(function,Number)的一個(gè)屬性,protorype是個(gè)對(duì)象。typeof的值是object。
如果看了上一小節(jié)的最后一個(gè)例子,對(duì)自定義的“類”應(yīng)該比較熟悉了。
在javascript中,可以說沒有方法,因?yàn)楹瘮?shù)和字符串一樣也是種數(shù)據(jù)類型,但類中的函數(shù)可以用this關(guān)鍵字。下面我說的類的屬性可以是方法,也可以指字段。
在一個(gè)自定義“類”中有中有幾個(gè)地方可以定義屬性。
?? a、函數(shù)名中直接定義。? 如Person.name。在這定義相當(dāng)于類名的屬性。靜態(tài)的,訪問的時(shí)候必須用Person.name來訪問,不能用new Person().name訪問,也訪問不到。
?? b、構(gòu)造函數(shù)的this.中。當(dāng)你用new function()時(shí),這些屬性就是你所持對(duì)象的屬性。用new Person().屬性? 來訪問。
?? c、構(gòu)建好對(duì)象以后,給對(duì)象增加屬性。和構(gòu)造函數(shù)中的屬性使用類似。
?? d、函數(shù)名的prototype中
?? e、父類或Object 的prototype中。
(1)對(duì)象屬性優(yōu)先級(jí)
通過運(yùn)行以下代碼,我們?cè)L問對(duì)象屬性優(yōu)先級(jí)如下:c>b>d>e
c種屬性必須在定義以后訪問才有效。a種屬性實(shí)例訪問不到。
javascrpt語言預(yù)定義的屬性不能用for in 得到。如toString
























(2)prototype屬性是只讀的
看如下代碼,你不要試圖通過變量改變?cè)蛯?duì)象的屬性。你也不可能改變,你只會(huì)通過c模式給對(duì)象增加一個(gè)屬性。
另外原型對(duì)象是所有實(shí)例共享的。理論上也不可以改變。




















































我個(gè)人從來不用javascript的“繼承”,始終認(rèn)為javascript實(shí)現(xiàn)的繼承不是真正的繼承。可能是受java”毒害“夠深。
在javascript中,我把繼承分為兩類: 類繼承,對(duì)象繼承。
(1)、prototype.js中的繼承
prototype.js中用如下代碼實(shí)現(xiàn)繼承。我認(rèn)為只是個(gè)屬性拷貝過程。










//Object.prototype.extend 感覺這句話沒必要,太模仿java了,想讓對(duì)象實(shí)例直接繼承。
??? a、prototype.js中的類繼承



























??? 我把這類型的繼承叫做類繼承,直接把你自己寫的對(duì)象屬性拷貝到原型對(duì)象中去。





































看了以上代碼,可能你會(huì)明白。直接拷貝類的原型對(duì)象確實(shí)可以實(shí)現(xiàn)某種概念上的繼承。
但要注意:在繼承體系中,Man的原型對(duì)象屬性方法最好不要用Man的實(shí)例屬性(name),因?yàn)榭赡躓oman中并沒有定義實(shí)例屬性name;也最好不要用Man)原型對(duì)象屬性字段(type),雖然type也被拷貝過來了,但值還是”男人“。
雖然有解決辦法,但javascript沒有很好的語法檢查工具,你用prototype.js的類繼承時(shí)小心處理。
b、prototype.js中的對(duì)象繼承
prototype.js 1.3.1
this.options = {
????? method:?????? 'post',
????? asynchronous: true,
????? parameters:?? ''
??? }.extend(options || {});
這個(gè)應(yīng)用比較簡(jiǎn)單,典型的對(duì)象之間屬性拷貝覆蓋。
總結(jié):關(guān)于prototype.js中繼承的實(shí)現(xiàn),我們當(dāng)成javascript對(duì)象的屬性拷貝可能在應(yīng)用中更好理解。建議大家仔細(xì)讀讀prototype.js代碼可能體會(huì)更深。模仿prototype.js中extend的應(yīng)用。感覺var Insertion = new Object(); 的實(shí)現(xiàn)比較經(jīng)典。
(2)、dojo-0.2.0-ajax中的繼承














dojo的繼承實(shí)現(xiàn)比較正統(tǒng),也是《javascript權(quán)威指南》中的實(shí)現(xiàn)方法。注意最后一句代碼可以實(shí)現(xiàn)子類訪問父類原型對(duì)象的方法。



































看看代碼,感覺混亂。
dojo一直沒時(shí)間仔細(xì)讀讀代碼。這部分詳細(xì)討論待續(xù)。
(3)、總結(jié)
關(guān)于javascript的繼承實(shí)現(xiàn),建議一般不要使用,感覺很亂,代碼可讀性較差。一般也沒有使用必要。詳細(xì)在《9、javascript對(duì)象使用指南》中討論。
javascript所有對(duì)象都繼承自O(shè)bject類。以下是Object類的一些屬性。原型對(duì)象
的一些屬性。
1、constructor屬性
從javascript1.1開始,每個(gè)對(duì)象都有這個(gè)屬性,它指向用來初始化改對(duì)象的構(gòu)造
函數(shù)
?































?
如以上代碼,可以知道
a、constructor的類型是函數(shù);
b、javascript內(nèi)部實(shí)現(xiàn)了很多函數(shù),如Object,Date都是函數(shù)由Function得到的
。
c、用原型對(duì)象實(shí)現(xiàn)的繼承中,也要設(shè)置子類的constructor。如果你的程序中用
到了constructor,可能會(huì)出錯(cuò)。
2、toString()方法
相當(dāng)于java Object類中toString方法。你alert()? + 等操作中就會(huì)調(diào)用這個(gè)方
法。 var s='1'+'2',會(huì)自動(dòng)把'1'? '2'? 轉(zhuǎn)化成String對(duì)象在執(zhí)行。
但數(shù)組定義自己的toString方法。alert(Array.prototype.toString)
如果對(duì)象或子類要調(diào)用父類的方法可以
?






?
3、toLocalString()方法
ECMAScript v3 javascript1.5中定義了這個(gè)方法。返回局部化的值。偶還不知道
什么用法。
4、valueof()
當(dāng)javascript與要將一個(gè)對(duì)象轉(zhuǎn)化成字符串之外的原始類型時(shí)調(diào)用它。
5、hasOwnProperty()方法
《javascript權(quán)威指南》說如果是非繼承的屬性返回true.但下列代碼反映,它檢
驗(yàn)對(duì)象的實(shí)例屬性。對(duì)原型屬性不會(huì)返回。
?






























6、propertyIsEnumerable
《javascript權(quán)威指南》如果用能 for( in )枚舉的屬性,這個(gè)方法返回true;
以下代碼說明《javascript權(quán)威指南》是錯(cuò)的。自己定義的原型對(duì)象屬性可以枚
舉,但返回false
?




















































7、isPrototypeOf方法
《javascript權(quán)威指南》如果調(diào)用對(duì)象是實(shí)際參數(shù)指定的對(duì)象的原型對(duì)象返回
true. 看代碼吧。
居然alert(Object.prototype.isPrototypeOf(Person));//true也是true.搞不懂
?


























?
8、總結(jié)
看《javascript權(quán)威指南》前,就知道toString方法。現(xiàn)在知道了些其他的方法
,但讓我更加混亂,《javascript權(quán)威指南》講的也有錯(cuò)誤。開發(fā)中建議大家除
了toString,其他屬性方法不要覆蓋也不要使用了。除了對(duì)這些方法十分清楚。就
我知道的javascript開源框架中好象沒用到這些。
1、廢話
?? 這部分將要描述瀏覽器為我們創(chuàng)建的對(duì)象。就是大家熟悉的window,document
等。一般書上都叫對(duì)象層次和文檔對(duì)象模型。用dom標(biāo)準(zhǔn)來說,一般瀏覽器都實(shí)現(xiàn)
了0級(jí)DOM,關(guān)于DOM標(biāo)準(zhǔn)我感覺知道0級(jí)就可以了。對(duì)于DOM標(biāo)準(zhǔn)W3C早已定義了1級(jí)
,2級(jí),三級(jí)也在標(biāo)準(zhǔn)化,問題是各個(gè)瀏覽器不完全實(shí)現(xiàn),尤其是IE的事件模型,
完全不和DOM一致。(不過prototype.js已經(jīng)做了很好的封裝)
??? 我這里不會(huì)講dom接口,更不會(huì)講各個(gè)瀏覽器的如何實(shí)現(xiàn)這些接口及區(qū)別。(
我也沒這能力)。而是要猜測(cè)一下瀏覽器是怎么用javascript定義這些接口或類
的。(注意是猜測(cè),個(gè)人理解)
2、引子
<SCRIPT LANGUAGE="JavaScript">
<!--
alert(document);
alert(typeof(document));
//alert(Document);//出錯(cuò)
function desc(obj){
? var ret='';
? for(var key in obj){
??? ret+=key+':'+obj[key]+'</br>';
? }
? return ret;
}
document.writeln(desc(document));
//-->
</SCRIPT>
以上簡(jiǎn)單的javascript代碼,不知大家提出過疑問沒有。
首先,document是個(gè)javascript對(duì)象,誰創(chuàng)建了它。;document的類是什么
(function Document(){....} 可能是new Document()創(chuàng)建了它);document有些
什么屬性或方法。這些對(duì)象與html關(guān)系是什么。這些對(duì)象與dom標(biāo)準(zhǔn)有什么關(guān)系。
接下來將試著回答這些問題。我會(huì)側(cè)重講述我的理解思路,而不是具體哪個(gè)方法
,接口。
3、一個(gè)簡(jiǎn)單的例子的深入理解
<SCRIPT LANGUAGE="JavaScript">
<!--
??? alert(document);//存在
??? alert(this.document==window.document);//true
//-->
</SCRIPT>
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<SCRIPT LANGUAGE="JavaScript">
??? alert(document.getElementById('xm'));//null
</SCRIPT>
</HEAD>
<SCRIPT LANGUAGE="JavaScript">
??? alert(document.getElementById('xm'));//null
</SCRIPT>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
??? alert(document.getElementById('xm'));//null
</SCRIPT>
<input type="text" id="xm">
<SCRIPT LANGUAGE="JavaScript">
??? alert(document.getElementById('xm'));//存在
</SCRIPT>
</BODY>
<SCRIPT LANGUAGE="JavaScript">
??? alert(document.getElementById('xm'));//存在
</SCRIPT>
</HTML>
上面代碼說明幾個(gè)問題:
a、window\this就是我在變量篇里面提到過的窗體的全局對(duì)象,document是它的
一個(gè)屬性,也叫全局屬性。
b、window,document在html最前面已經(jīng)存在了。我們可以隨處使用document對(duì)象
。
c、對(duì)于輸入框按鈕這類html標(biāo)記的javascript對(duì)象只有在解釋過以后才能訪問到
。當(dāng)然我們編碼用到這些對(duì)象時(shí),都在body.onload或鼠標(biāo)觸發(fā),一般不會(huì)出錯(cuò)。
d、例子中的document.getElementById('xm')javascript對(duì)象和我們自己創(chuàng)建的
javascript對(duì)象有什么區(qū)別呢?從應(yīng)用角度看沒有區(qū)別,只是自己定義的對(duì)象由
自己new來初始化,而document.getElementById('xm')有瀏覽器為我們初始化對(duì)
象,我們直接用方法得到句柄就可以了(有多種方法)。
e、我們?cè)趺粗肋@些對(duì)象的用法呢?查看w3c DOM參考嗎?我認(rèn)為不用。
4、瀏覽器為我們創(chuàng)建的對(duì)象與我們自己定義的對(duì)象的區(qū)別。
<input type="text" id="xm" value="aaa">
<INPUT TYPE="button" value='click me' onclick="alert
(document.getElementById('xm').value);
alert(document.getElementById('myxm').value);">
<br>
<SCRIPT LANGUAGE="JavaScript">
<!--
function desc(obj){
? var ret='';
? for(var key in obj){
??? ret+=key+':'+obj[key]+'</br>';
? }
? return ret;
}
function MyText(id,value){
??? this.id=id;
?this.outHtml='<input type=text id='+id+' value='+value+'>';
?this.toString=function(){
??????? return this.outHtml;
?}
?//...
?//...
?//...
}
//document.writeln(desc(document.getElementById('xm')));
var myText=new MyText('myxm','zkj');
document.writeln(myText);
//-->
</SCRIPT>
希望你仔細(xì)的看看上面代碼的執(zhí)行結(jié)果。可能你會(huì)得到更震撼的想法來。暫時(shí)我
有以下幾個(gè)感想:
a、我們自己也可以寫一個(gè)界面控件,如果把屬性建立全的話,完全可以復(fù)原瀏覽
器的內(nèi)建類。
b、反過來,對(duì)于瀏覽器為我們創(chuàng)建的對(duì)象,我們可以當(dāng)成自己的對(duì)象一樣使用。
看看prototype.js中,使用了內(nèi)建對(duì)象的方法。
escapeHTML: function() {
??? var div = document.createElement('div');
??? var text = document.createTextNode(this);
??? div.appendChild(text);
??? return div.innerHTML;
? },
? unescapeHTML: function() {
??? var div = document.createElement('div');
??? div.innerHTML = this.stripTags();
??? return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
? },
c、大家可以打開描述注釋,看看<input >到底包含哪些屬性和方法。注意
outerHTML屬性的值是什么,在網(wǎng)頁上表示什么。可以看出javascript對(duì)象的
outerHTML屬性就是html(xhtml)規(guī)范中的標(biāo)簽。這樣給了我們寫javascriptUI控
件的新思路,一個(gè)控件就是一個(gè)javascript對(duì)象(其實(shí)很多人都這樣做了,但好
象都是innerHtml等等)。可以象asp.net或jsf那樣編寫組合控件。
大家可以看一下ActiveWidgets代碼(與我的思路有些差別),我認(rèn)為這種基于
html標(biāo)簽的UI控件無論性能、開發(fā)人員使用難度上都不錯(cuò)。
對(duì)于dojo的widget這種做UI做法我個(gè)人不很贊同,完全用div,圖片實(shí)現(xiàn)了一便
html的UI標(biāo)簽。性能不好,開發(fā)人員上手不容易,美工更不能修改,另外圖片都
是定死的,界面也比較單調(diào),也不好修改。
對(duì)于自己實(shí)現(xiàn)javascript控件,我認(rèn)為在htmlUI基礎(chǔ)上就可以了,畢竟自己實(shí)現(xiàn)
存在的UI難度不小。把html的標(biāo)準(zhǔn)UI組合成新的控件。例如,我們可以很容易的
實(shí)現(xiàn)一個(gè)包括? (登陸 密碼 驗(yàn)證碼 確認(rèn))? 的組合javascript控件
d、dom標(biāo)準(zhǔn)與瀏覽器對(duì)象
打開document.writeln(desc(document.getElementById('xm')));,你可以看到<
input type="text">的所有屬性。這些屬性 ”dom標(biāo)準(zhǔn)“,之所以加引號(hào),DOM標(biāo)
準(zhǔn)我們有很多誤解,認(rèn)為DOM標(biāo)準(zhǔn)是個(gè)什么高不可及、不可違抗的、復(fù)雜的東西。
首先:我們接觸了靜態(tài)HTML,xml,有了DOM對(duì)象模型(熟悉java的都知道java的實(shí)
現(xiàn)),但javascript語言的特點(diǎn)使不能象java,c++那樣來實(shí)現(xiàn)DOM對(duì)象模型。例如
input 繼承了 HTMLElement,HTMLElement定義的一堆屬性。按照dom標(biāo)準(zhǔn),所有瀏
覽器實(shí)現(xiàn) input javascript對(duì)象時(shí)都必須把這些屬性加上,這就叫符合標(biāo)準(zhǔn)。其
實(shí)說白了:DOM標(biāo)準(zhǔn)就是瀏覽器為我們實(shí)現(xiàn)的javascript代碼的總和。(可以瀏覽
器廠商不完全實(shí)現(xiàn))
看protorype.js的代碼
為了支持多了瀏覽器,定義下面代碼。說明有的瀏覽器網(wǎng)頁全局變量里有Element
,Event,有些瀏覽器沒給我們定義。所以只能這樣了。
if (!window.Element) {
? var Element = new Object();
}
if (!window.Event) {
? var Event = new Object();
}
還有用AJAX技術(shù)時(shí)
'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0', 其實(shí)很簡(jiǎn)
單,就是瀏覽器中有沒有這些javascript實(shí)現(xiàn)了。所有大家在DWR框架中用iframe
實(shí)現(xiàn)了一個(gè)javascript? XMLHTTP類。
e、與xhtml標(biāo)準(zhǔn)的矛盾
在xhtml中,<input type="button"> 雙引號(hào)是必須的,但outerHTML屬性中卻沒
雙引號(hào)。還沒想明白。
5、瀏覽器為我們創(chuàng)建了幾類對(duì)象
a、全局對(duì)象window或this。其實(shí)javascript的全局變量、全局方法(如
Math,setTimeout())都可以由window對(duì)象訪問。另外瀏覽器的特殊函數(shù)或?qū)傩浴?/p>
(如window.status,window.alert())
b、document對(duì)象。包括圖片,applet,form等屬性,可能我們用的最多。也是訪
問我們可見的元素的入口(document.getElementById),也提供了動(dòng)態(tài)創(chuàng)建html
標(biāo)簽的方法。如var t=new Text("test");沒有這樣方法,只能 var
t=document.creatTextNode("test");都由document提供的工廠方法來創(chuàng)建。
c、頁面中的html標(biāo)簽,當(dāng)解釋執(zhí)行過,瀏覽器會(huì)為你初始化對(duì)象,放到document
對(duì)象中去。
6、對(duì)DOM標(biāo)準(zhǔn)的認(rèn)識(shí)
DOM標(biāo)準(zhǔn)定義了接口,沒有定義類。瀏覽器為我們實(shí)現(xiàn)了這些接口,實(shí)現(xiàn)這些接口
的類我們也看不見。所以這里接口的含義和java中接口的含義不同。
例如我們常用的document對(duì)象
DOM標(biāo)準(zhǔn)中定義了個(gè)Document接口,實(shí)現(xiàn)HTMLElemnt接口。
Document接口和HTMLElemnt接口在DOM標(biāo)準(zhǔn)中定義了很多屬性和方法。
注意我們使用的document對(duì)象是瀏覽器為我們創(chuàng)建的javascript對(duì)象,到底
document對(duì)象有哪些屬性和方法是有瀏覽器決定的,而不是由DOM標(biāo)準(zhǔn)決定的。
在這里javascript世界里沒有繼承概念,所以DOM標(biāo)準(zhǔn)定義的接口,對(duì)于我們開發(fā)
人員來說只能當(dāng)成一個(gè)參考手冊(cè),象javadoc。
7、如何寫出跨瀏覽器的javascript代碼
?? 這難度大了點(diǎn).但說穿了,只要我們用javascript代碼把瀏覽器沒符合DOM標(biāo)準(zhǔn)
的代碼補(bǔ)全就好了。但DOM標(biāo)準(zhǔn)之大不是一般人能全部搞清楚的,瀏覽器廠商也使
壞,讓這個(gè)工作更難了。?? 現(xiàn)在好象有個(gè)誤區(qū),人們寫javascript都喜歡按照
DOM標(biāo)準(zhǔn)來寫。如果我們按照各個(gè)瀏覽器實(shí)現(xiàn)DOM標(biāo)準(zhǔn)的交集寫代碼的話,可能會(huì)
更好點(diǎn)。
凡是有該標(biāo)志的文章,都是該blog博主Caoer(草兒)原創(chuàng),凡是索引、收藏
、轉(zhuǎn)載請(qǐng)注明來處和原文作者。非常感謝。