1、廢話
?? 這部分將要描述瀏覽器為我們創(chuàng)建的對(duì)象。就是大家熟悉的window,document

等。一般書上都叫對(duì)象層次和文檔對(duì)象模型。用dom標(biāo)準(zhǔn)來(lái)說(shuō),一般瀏覽器都實(shí)現(xiàn)

了0級(jí)DOM,關(guān)于DOM標(biāo)準(zhǔn)我感覺(jué)知道0級(jí)就可以了。對(duì)于DOM標(biāo)準(zhǔn)W3C早已定義了1級(jí)

,2級(jí),三級(jí)也在標(biāo)準(zhǔn)化,問(wèn)題是各個(gè)瀏覽器不完全實(shí)現(xiàn),尤其是IE的事件模型,

完全不和DOM一致。(不過(guò)prototype.js已經(jīng)做了很好的封裝)
??? 我這里不會(huì)講dom接口,更不會(huì)講各個(gè)瀏覽器的如何實(shí)現(xiàn)這些接口及區(qū)別。(

我也沒(méi)這能力)。而是要猜測(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代碼,不知大家提出過(guò)疑問(wèn)沒(méi)有。
首先,document是個(gè)javascript對(duì)象,誰(shuí)創(chuàng)建了它。;document的類是什么

(function Document(){....} 可能是new Document()創(chuàng)建了它);document有些

什么屬性或方法。這些對(duì)象與html關(guān)系是什么。這些對(duì)象與dom標(biāo)準(zhǔn)有什么關(guān)系。

接下來(lái)將試著回答這些問(wè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>

上面代碼說(shuō)明幾個(gè)問(wèn)題:
a、window\this就是我在變量篇里面提到過(guò)的窗體的全局對(duì)象,document是它的

一個(gè)屬性,也叫全局屬性。
b、window,document在html最前面已經(jīng)存在了。我們可以隨處使用document對(duì)象


c、對(duì)于輸入框按鈕這類html標(biāo)記的javascript對(duì)象只有在解釋過(guò)以后才能訪問(wèn)到

。當(dāng)然我們編碼用到這些對(duì)象時(shí),都在body.onload或鼠標(biāo)觸發(fā),一般不會(huì)出錯(cuò)。
d、例子中的document.getElementById('xm')javascript對(duì)象和我們自己創(chuàng)建的

javascript對(duì)象有什么區(qū)別呢?從應(yīng)用角度看沒(méi)有區(qū)別,只是自己定義的對(duì)象由

自己new來(lái)初始化,而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ì)得到更震撼的想法來(lái)。暫時(shí)我

有以下幾個(gè)感想:
a、我們自己也可以寫一個(gè)界面控件,如果把屬性建立全的話,完全可以復(fù)原瀏覽

器的內(nèi)建類。
b、反過(guò)來(lái),對(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)頁(yè)上表示什么。可以看出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控件無(wú)論性能、開發(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語(yǔ)言的特點(diǎn)使不能象java,c++那樣來(lái)實(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í)說(shuō)白了:DOM標(biāo)準(zhǔn)就是瀏覽器為我們實(shí)現(xiàn)的javascript代碼的總和。(可以瀏覽

器廠商不完全實(shí)現(xiàn))
看protorype.js的代碼
為了支持多了瀏覽器,定義下面代碼。說(shuō)明有的瀏覽器網(wǎng)頁(yè)全局變量里有Element

,Event,有些瀏覽器沒(méi)給我們定義。所以只能這樣了。

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)

單,就是瀏覽器中有沒(méi)有這些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屬性中卻沒(méi)

雙引號(hào)。還沒(méi)想明白。

5、瀏覽器為我們創(chuàng)建了幾類對(duì)象
a、全局對(duì)象window或this。其實(shí)javascript的全局變量、全局方法(如

Math,setTimeout())都可以由window對(duì)象訪問(wèn)。另外瀏覽器的特殊函數(shù)或?qū)傩浴?/p>

(如window.status,window.alert())
b、document對(duì)象。包括圖片,applet,form等屬性,可能我們用的最多。也是訪

問(wèn)我們可見(jiàn)的元素的入口(document.getElementById),也提供了動(dòng)態(tài)創(chuàng)建html

標(biāo)簽的方法。如var t=new Text("test");沒(méi)有這樣方法,只能 var

t=document.creatTextNode("test");都由document提供的工廠方法來(lái)創(chuàng)建。
c、頁(yè)面中的html標(biāo)簽,當(dāng)解釋執(zhí)行過(guò),瀏覽器會(huì)為你初始化對(duì)象,放到document

對(duì)象中去。

6、對(duì)DOM標(biāo)準(zhǔn)的認(rèn)識(shí)
DOM標(biāo)準(zhǔn)定義了接口,沒(méi)有定義類。瀏覽器為我們實(shí)現(xiàn)了這些接口,實(shí)現(xiàn)這些接口

的類我們也看不見(jià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世界里沒(méi)有繼承概念,所以DOM標(biāo)準(zhǔn)定義的接口,對(duì)于我們開發(fā)

人員來(lái)說(shuō)只能當(dāng)成一個(gè)參考手冊(cè),象javadoc。

7、如何寫出跨瀏覽器的javascript代碼
?? 這難度大了點(diǎn).但說(shuō)穿了,只要我們用javascript代碼把瀏覽器沒(méi)符合DOM標(biāo)準(zhǔn)

的代碼補(bǔ)全就好了。但DOM標(biāo)準(zhǔn)之大不是一般人能全部搞清楚的,瀏覽器廠商也使

壞,讓這個(gè)工作更難了。?? 現(xiàn)在好象有個(gè)誤區(qū),人們寫javascript都喜歡按照

DOM標(biāo)準(zhǔn)來(lái)寫。如果我們按照各個(gè)瀏覽器實(shí)現(xiàn)DOM標(biāo)準(zhǔn)的交集寫代碼的話,可能會(huì)

更好點(diǎn)。

?


?