理解Javascript中類的定義

鴨脖發表於2012-06-27

關於如何在Javascript中定義類,網上可以找到不少的文章。在開始講之前,還是先來看看定義類的兩種基本方式吧:

(1) 利用函式構造型別。

function Foo(text, url) {
	this.text = text;
	this.url = url;
	
	this.render = function() {
		document.write('<a href="' + this.url + '">' + this.text + '</a>');
	}
}
(2) 利用原型prototype。
function Bar(text, url) {
	this.text = text;
	this.url = url;
}
Bar.prototype = {
	render : function() {
		document.write('<a href="' + this.url + '">' + this.text + '</a>');
	}
}

  程式碼並不複雜,相信大多數人看完之後都會曉得怎麼使用了。但是當我第一次看到這種類的定義方式的時候覺得很奇怪,很長一段時間裡都是知其然而不知其所以然。如果你有和我一樣的困惑,也許可以分享一下我的一點經驗。

  先來看看怎麼使用定義好的型別,

var a = new Foo('Link A', 'http://www.cnblogs.com');
var b = new Bar('Link B', 'http://www.csdn.net');
a.render();
b.render();

  跟很多物件導向語言(如C#)的使用方法一樣,都是使用new關鍵字例項化類,而且當你用instanceof來測試它們是不是相應型別時,都可以得到預望的答案。兩種不同方式定義出來的型別Foo和Bar很多時候使用起來並沒有什麼不同。

  但它們在原理上是完全不同,方式1,是在建構函式中動態中建立類的成員,這就意味著每個Foo的例項它們的render方法其實是兩個完全獨立的函式;而方式2,則是通過原型prototype的方式將類的共享成員與類的例項繫結在一起,所以每個Bar例項的render方法都是指向同一個方法,它是靜態的。請看以下程式碼:

document.write(Object.prototype==String.prototype);
var c = new Foo('Link C', 'http://www.asp.net');
document.write(c.render == a.render);  // false
var d = new Bar('Link D', 'http://www.klesh.cn);
document.write(d.render == b.render);  // true

  Foo在例項化後就是一個獨立的個體,它的任何改動不會影響到原來的型別定義,也不會影響到其他的例項;而Bar則不同,它的所有例項都依然受prototype的影響,通過對Bar.prototype的修改或擴充套件,可以影響到所有包括已經例項化的例項。回過頭來看Foo,由於它的成員,特別是成員函式是動態建立的,利用閉包,則可以模擬物件導向中的“私有成員”,這一點內容會很長,稍後有時間再和大家分享。

  兩種方式各有特點。但是最後,嚴格來說,無論什麼方式,都只能說是“模擬自定義型別”,因為在基於物件的Javascript中,它事實上是沒有原生的“自定義型別”的概念的(這一點也很長,暫不細說)。

  最後推薦大家一般使用方式2來在Javascript模擬自定義類,一來,速度上會比較快,而且還可以通過prototype對型別進行修改,除非你有需要到“私有成員”(好像也有人叫“閉包“)……除非你有需要用到閉包來模擬“私有成員”。

刪除線和斜體部分根據木野狐同志的意見修正。

摘自http://www.cnblogs.com/Klesh/archive/2007/09/28/understanding-classs-definition-in-javascript.html

相關文章