天天看點

Javascript原型模式總結梳理

  在大多數面向對象語言中,對象總是由類中執行個體化而來,類和對象的關系就像模具跟模件一樣。javascript中沒有類的概念,就算es6中引入的class也不過是一種文法糖,本質上還是利用原型實作。在原型程式設計語言中,類并不是必需的,對象不一定需要由類執行個體化而來,而是通過克隆另外一個對象來得到。

  原型模式是用來建立對象的一種模式。在以類為中心的語言中,要建立一個對象首先要指定這個對象的類型,然後執行個體化一個對象。使用原型模式建立對象時不必關心對象的具體類型,而是找到一個對象,然後通過克隆來建立一個一模一樣的對象。是以在前者中如果要根據一個對象建立多個相同的對象,我們需要先儲存這個對象的所有屬性資訊,然後将屬性資訊設定到新建立的對象上,而在原型模式中我們隻需要使用克隆就能完成同樣的功能。

  在某些玄幻小說中經常會出現某些修真大能,以分身的形式遊走世間。這個過程很适合原型模式的應用:

es5提供了原生的克隆方法:object.create,不支援這個方法的浏覽器可以使用如下代碼:

通過以上代碼,我們看到了如何通過原型模式來克隆出一個一模一樣的的對象。原型模式的真正意義并非建立一個一模一樣的對象,而是提供一種建立對象的方式,javascript的面向對象機制是基于原型模式的,他的對象系統就是使用原型模式,通過克隆來建立的,克隆是建立一個對象的過程和手段。以繼承為例:

  基于原型的繼承體系,子類的每次執行個體化都是對其構造函數的prototype屬性的克隆。是以每次建立developer對象,其實都是在對p對象的克隆。

  在java等以類為中心的面向對象語言中,經常使用new執行個體化一個對象。但是javascript是基于原型的面向對象語言,在這裡new運算符建立對象的方式與java中的new運算符并不相同,javascript中的new運算符也是通過克隆來執行個體化對象的,克隆的是構造器函數的原型對象,new運算符的作用等同于如下代碼:

  從這我們也可以看出,javascript的原型實際上存在着諸多沖突,它的某些複雜文法看起來就像那些基于類的語言,這掩蓋了它的原型機制。是以jquery中盡量避免使用new運算符來建立對象。

  根據前面所說javascript中新建立的對象都是基于原有對象的克隆,是以在javascript中存在一個最原始的對象:object.prototype,所有對象都是由它克隆而來。

  這裡所說的克隆是在javascript原型模式這一大環境下的一種語義表達,在計算機的實體世界中并不存在真正的克隆。是以這裡對于克隆應當了解為産生一個擁有__proto__屬性指向原對象的對象的過程,原對象成為被克隆的對象,也就是構造函數的prototype對象。

  擁有以上共識後,我們可以得到在javascript中原型程式設計的基本規則:

javascript中絕大多數資料都是對象

要得到一個對象,不是通過執行個體化類,而是找到一個對象作為原型并克隆它

對象會記住它的原型

如果對象無法響應某個請求,他會把這個請求委托給它自己的原型

參考書籍:

《javascript語言精粹》

《javascript設計模式與開發實踐》

繼續閱讀