| 導購 | 订阅 | 在线投稿
分享
 
 
 

領悟JavaScript中的面向對象

來源:互聯網  2008-08-19 06:51:07  評論

JavaScript 是面向對象的。但是不少人對這一點理解得並不全面。

在 JavaScript 中,對象分爲兩種。一種可以稱爲「普通對象」,就是我們所普遍理解的那些:數字、日期、用戶自定義的對象(如:{})等等。

還有一種,稱爲「方法對象」,就是我們通常定義的 function。你可能覺得奇怪:方法就是方法,怎麽成了對象了?但是在 JavaScript 中,方法的確是被當成對象來處理的。下面是一個簡單的例子:

JavaScript代碼

function func() {alert('Hello!');}

alert(func.toString());

在這個例子中,func 雖然是作爲一個方法定義的,但它自身卻包含一個 toString 方法,說明 func 在這裏是被當成一個對象來處理的。更准確的說,func 是一個「方法對象」。下面是例子的繼續:

JavaScript代碼

func.name = 「I am func.」;

alert(func.name);

我們可以任意的爲 func 設置屬性,這更加證明了 func 就是一個對象。那麽方法對象和普通對象的區別在哪裏呢?首先方法對象當然是可以執行的,在它後面加上一對括號,就是執行這個方法對象了。

JavaScript代碼

func();

所以,方法對象具有二重性。一方面它可以被執行,另一方面它完全可以被當成一個普通對象來使用。這意味著什麽呢?這意味著方法對象是可以完全獨立于其他對象存在的。這一點我們可以同 Java 比較一下。在 Java 中,方法必須在某一個類中定義,而不能單獨存在。而 JavaScript 中就不需要。

方法對象獨立于其他方法,就意味著它能夠被任意的引用和傳遞。下面是一個例子:

JavaScript代碼

function invoke(f) {

f();

}

invoke(func);

將一個方法對象 func 傳遞給另一個方法對象 invoke,讓後者在適當的時候執行 func。這就是所謂的「回調」了。另外,方法對象的這種特殊性,也使得 this 關鍵字不容易把握。這方面相關文章不少,這裏不贅述了。

除了可以被執行以外,方法對象還有一個特殊的功用,就是它可以通過 new 關鍵字來創建普通對象。

話說每一個方法對象被創建時,都會自動的擁有一個叫 prototype 的屬性。這個屬性並無什麽特別之處,它和其他的屬性一樣可以訪問,可以賦值。不過當我們用 new 關鍵字來創建一個對象的時候,prototype 就起作用了:它的值(也是一個對象)所包含的所有屬性,都會被複制到新創建的那個對象上去。下面是一個例子:

JavaScript代碼

func.prototype.name=」prototype of func」;

var f = new func();

alert(f.name);

執行的過程中會彈出兩個對話框,後一個對話框表示 f 這個新建的對象從 func.prototype 那裏拷貝了 name 屬性。而前一個對話框則表示 func 被作爲方法執行了一遍。你可能會問了,爲什麽這個時候要還把 func 執行一遍呢?其實這個時候執行 func,就是起「構造函數」的作用。爲了形象的說明,我們重新來一遍:

JavaScript代碼

function func() {

this.name=」name has been changed.」

}

func.prototype.name=」prototype of func」;

var f = new func();

alert(f.name);

你就會發現 f 的 name 屬性不再是"prototype of func",而是被替換成了"name has been changed"。這就是 func 這個對象方法所起到的「構造函數」的作用。所以,在 JavaScript 中,用 new 關鍵字創建對象是執行了下面三個步驟的:

創建一個新的普通對象;

將方法對象的 prototype 屬性的所有屬性複制到新的普通對象中去。

以新的普通對象作爲上下文來執行方法對象。

對于「new func()」這樣的語句,可以描述爲「從 func 創建一個新對象」。總之,prototype 這個屬性的唯一特殊之處,就是在創建新對象的時候了。

那麽我們就可以利用這一點。比如有兩個方法對象 A 和 B,既然從 A 創建的新對象包含了所有 A.prototype 的屬性,那麽我將它賦給 B.prototype,那麽從 B 創建的新對象不也有同樣的屬性了?寫成代碼就是這樣:

XML/HTML代碼

A.prototype.hello = function(){alert('Hello!');}

B.prototype = new A();

new B().hello();

這就是 JavaScript 的所謂「繼承」了,其實質就是屬性的拷貝,這裏利用了 prototype 來實現。如果不用 prototype,那就用循環了,效果是一樣的。所謂「多重繼承」,自然就是到處拷貝了。

JavaScript 中面向對象的原理,就是上面這些了。自始至終我都沒提到「類」的概念,因爲 JavaScript 本來就沒有「類」這個東西。面向對象可以沒有類嗎?當然可以。先有類,然後再有對象,這本來就不合理,因爲類本來是從對象中歸納出來的,先有對象再有類,這才合理。像下面這樣的:

XML/HTML代碼

var o = {}; // 我發現了一個東西。

o.eat = function(){return "I am eating."} // 我發現它會吃;

o.sleep = function(){return "ZZZzzz..."} // 我發現它會睡;

o.talk = function(){return "Hi!"} // 我發現它會說話;

o.think = function(){return "Hmmm..."} // 我發現它還會思考。

var Human = new Function(); // 我決定給它起名叫「人」。

Human.prototype = o; // 這個東西就代表了所有「人」的概念。

var h = new Human(); // 當我發現其他同它一樣的東西,

alert(h.talk()) // 我就知道它也是「人」了!

JavaScript 是面向對象的。但是不少人對這一點理解得並不全面。 在 JavaScript 中,對象分爲兩種。一種可以稱爲「普通對象」,就是我們所普遍理解的那些:數字、日期、用戶自定義的對象(如:{})等等。 還有一種,稱爲「方法對象」,就是我們通常定義的 function。你可能覺得奇怪:方法就是方法,怎麽成了對象了?但是在 JavaScript 中,方法的確是被當成對象來處理的。下面是一個簡單的例子: JavaScript代碼 function func() {alert('Hello!');} alert(func.toString()); 在這個例子中,func 雖然是作爲一個方法定義的,但它自身卻包含一個 toString 方法,說明 func 在這裏是被當成一個對象來處理的。更准確的說,func 是一個「方法對象」。下面是例子的繼續: JavaScript代碼 func.name = 「I am func.」; alert(func.name); 我們可以任意的爲 func 設置屬性,這更加證明了 func 就是一個對象。那麽方法對象和普通對象的區別在哪裏呢?首先方法對象當然是可以執行的,在它後面加上一對括號,就是執行這個方法對象了。 JavaScript代碼 func(); 所以,方法對象具有二重性。一方面它可以被執行,另一方面它完全可以被當成一個普通對象來使用。這意味著什麽呢?這意味著方法對象是可以完全獨立于其他對象存在的。這一點我們可以同 Java 比較一下。在 Java 中,方法必須在某一個類中定義,而不能單獨存在。而 JavaScript 中就不需要。 方法對象獨立于其他方法,就意味著它能夠被任意的引用和傳遞。下面是一個例子: JavaScript代碼 function invoke(f) { f(); } invoke(func); 將一個方法對象 func 傳遞給另一個方法對象 invoke,讓後者在適當的時候執行 func。這就是所謂的「回調」了。另外,方法對象的這種特殊性,也使得 this 關鍵字不容易把握。這方面相關文章不少,這裏不贅述了。 除了可以被執行以外,方法對象還有一個特殊的功用,就是它可以通過 new 關鍵字來創建普通對象。 話說每一個方法對象被創建時,都會自動的擁有一個叫 prototype 的屬性。這個屬性並無什麽特別之處,它和其他的屬性一樣可以訪問,可以賦值。不過當我們用 new 關鍵字來創建一個對象的時候,prototype 就起作用了:它的值(也是一個對象)所包含的所有屬性,都會被複制到新創建的那個對象上去。下面是一個例子: JavaScript代碼 func.prototype.name=」prototype of func」; var f = new func(); alert(f.name); 執行的過程中會彈出兩個對話框,後一個對話框表示 f 這個新建的對象從 func.prototype 那裏拷貝了 name 屬性。而前一個對話框則表示 func 被作爲方法執行了一遍。你可能會問了,爲什麽這個時候要還把 func 執行一遍呢?其實這個時候執行 func,就是起「構造函數」的作用。爲了形象的說明,我們重新來一遍: JavaScript代碼 function func() { this.name=」name has been changed.」 } func.prototype.name=」prototype of func」; var f = new func(); alert(f.name); 你就會發現 f 的 name 屬性不再是"prototype of func",而是被替換成了"name has been changed"。這就是 func 這個對象方法所起到的「構造函數」的作用。所以,在 JavaScript 中,用 new 關鍵字創建對象是執行了下面三個步驟的: 創建一個新的普通對象; 將方法對象的 prototype 屬性的所有屬性複制到新的普通對象中去。 以新的普通對象作爲上下文來執行方法對象。 對于「new func()」這樣的語句,可以描述爲「從 func 創建一個新對象」。總之,prototype 這個屬性的唯一特殊之處,就是在創建新對象的時候了。 那麽我們就可以利用這一點。比如有兩個方法對象 A 和 B,既然從 A 創建的新對象包含了所有 A.prototype 的屬性,那麽我將它賦給 B.prototype,那麽從 B 創建的新對象不也有同樣的屬性了?寫成代碼就是這樣: XML/HTML代碼 A.prototype.hello = function(){alert('Hello!');} B.prototype = new A(); new B().hello(); 這就是 JavaScript 的所謂「繼承」了,其實質就是屬性的拷貝,這裏利用了 prototype 來實現。如果不用 prototype,那就用循環了,效果是一樣的。所謂「多重繼承」,自然就是到處拷貝了。 JavaScript 中面向對象的原理,就是上面這些了。自始至終我都沒提到「類」的概念,因爲 JavaScript 本來就沒有「類」這個東西。面向對象可以沒有類嗎?當然可以。先有類,然後再有對象,這本來就不合理,因爲類本來是從對象中歸納出來的,先有對象再有類,這才合理。像下面這樣的: XML/HTML代碼 var o = {}; // 我發現了一個東西。 o.eat = function(){return "I am eating."} // 我發現它會吃; o.sleep = function(){return "ZZZzzz..."} // 我發現它會睡; o.talk = function(){return "Hi!"} // 我發現它會說話; o.think = function(){return "Hmmm..."} // 我發現它還會思考。 var Human = new Function(); // 我決定給它起名叫「人」。 Human.prototype = o; // 這個東西就代表了所有「人」的概念。 var h = new Human(); // 當我發現其他同它一樣的東西, alert(h.talk()) // 我就知道它也是「人」了!
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有