??? b、千萬別亂定義Object.prototype原型對象。prototype.js中加了個extends被人說了半天。但我們自己寫類庫時,千萬別嘗試改Object的prototype。
??? c、別用javacript語言模仿java來寫代碼。想上面的,需要一個person的“類”,并不是非需要定義一個,注意javascript對象的屬性是可以隨意增加或刪除的。并不象java那樣在類中寫死。
??? d、就上面兩段代碼有什么區別呢?可以簡單的說是person繼承了Object”類“。javascript中對象的繼承是用prototype來實現的,后面我們討論prototype原型對象。
??? e、那我們應用的時候到底是否該自己定義自己的構造函數(如person),還是直接使用Object呢?這是個復雜的問題,我個人來說喜歡多用Object.
在這里Person是個函數,但我們還可以定義它的屬性(type)。而Person有Object實例的特性(for in、可以定義屬性),但Person不是Object的實例。
我理解function返回的數據類型是和Object同等級的數據類型。它有Object實例(new Object())的一些特性,但它不是Object的實例,因為它沒有繼承Object.prototype.toString=function(){return 'myToString'};但我們Person.toString=function(){return 'Person toString'};改變了覆蓋了方法。
在《javascript權威指南》中,作者用這個特性實現了“類方法、類變量”static方法,與java中不同,這些方法不能用new Person()來調用。
原型對象prototype是Object或與之同等級的對象如(function,Number)的一個屬性,protorype是個對象。typeof的值是object。
javascript所有對象都繼承自Object類。以下是Object類的一些屬性。原型對象
的一些屬性。
1、constructor屬性
從javascript1.1開始,每個對象都有這個屬性,它指向用來初始化改對象的構造
函數
?
<SCRIPT?LANGUAGE="JavaScript">
<!--

function?Person()
{}
var?o=new?Person();

alert(typeof(Person.constructor));
alert(o.constructor);
alert(Person.constructor);
alert(Function.constructor);
alert(Object.constructor)

alert(new?Date().constructor);
alert(Date.constructor);



function?Man()
{

}
Man.prototype=new?Person();
alert(Man.constructor);
o=new?Man();
alert(o.constructor)
Man.prototype.constructor=Man;
alert(o.constructor)
//-->
</SCRIPT>

?
如以上代碼,可以知道
a、constructor的類型是函數;
b、javascript內部實現了很多函數,如Object,Date都是函數由Function得到的
。
c、用原型對象實現的繼承中,也要設置子類的constructor。如果你的程序中用
到了constructor,可能會出錯。
2、toString()方法
相當于java Object類中toString方法。你alert()? + 等操作中就會調用這個方
法。 var s='1'+'2',會自動把'1'? '2'? 轉化成String對象在執行。
但數組定義自己的toString方法。alert(Array.prototype.toString)
如果對象或子類要調用父類的方法可以
?
<SCRIPT?LANGUAGE="JavaScript">
<!--
alert([1,2,3].toLocalString())
alert(Object.prototype.toString.apply([1,2,3]));
//-->
</SCRIPT>?
3、toLocalString()方法
ECMAScript v3 javascript1.5中定義了這個方法。返回局部化的值。偶還不知道
什么用法。
4、valueof()
當javascript與要將一個對象轉化成字符串之外的原始類型時調用它。
5、hasOwnProperty()方法
《javascript權威指南》說如果是非繼承的屬性返回true.但下列代碼反映,它檢
驗對象的實例屬性。對原型屬性不會返回。
?
<SCRIPT?LANGUAGE="JavaScript">
<!--

function?Person(name)
{
????this.name=name;
}

Person.prototype.setAge=function(age)
{
????this.age=age;
}

Person.prototype.toString=function()
{
????return?'name:'+this.name+'?age:'+this.age;
}
var?o=new?Person('zkj');
o.setAge(25);
alert(o)
alert(o.hasOwnProperty("name"));
alert(o.hasOwnProperty("age"));
alert(o.hasOwnProperty("setAge"));
alert(o.hasOwnProperty("toString"));

alert(Person.prototype.hasOwnProperty("setAge"));
//-->
</SCRIPT>


6、propertyIsEnumerable
《javascript權威指南》如果用能 for( in )枚舉的屬性,這個方法返回true;
以下代碼說明《javascript權威指南》是錯的。自己定義的原型對象屬性可以枚
舉,但返回false
?
<SCRIPT?LANGUAGE="JavaScript">
<!--

function?Person(name)
{
????this.name=name;
}

Person.prototype.setAge=function(age)
{
????this.age=age;
}

Person.prototype.toString=function()
{
????return?'name:'+this.name+'?age:'+this.age;
}
var?o=new?Person('zkj');
o.setAge(25);
alert(o.propertyIsEnumerable('setAge'));
var?desc='';

for(var?key?in?o)
{
????desc+=key+'??';

????if(o.hasOwnProperty(key))
{
????????desc+='?是實例對象?';

?}else
{
????????desc+='?不是實例對象?';
?}

?if(o.propertyIsEnumerable(key))
{
????????desc+='?能被枚舉?';

?}else
{
????????desc+='?不能被枚舉?';
?}

?desc+='\r\n';
}
alert(desc);

//-->
</SCRIPT>


7、isPrototypeOf方法
《javascript權威指南》如果調用對象是實際參數指定的對象的原型對象返回
true. 看代碼吧。
居然alert(Object.prototype.isPrototypeOf(Person));//true也是true.搞不懂
?
<SCRIPT?LANGUAGE="JavaScript">
<!--

function?Person(name)
{
????this.name=name;
}

Person.prototype.setAge=function(age)
{
????this.age=age;
}

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