英文原文位址:http://sporto.github.com/blog/2013
/02/22/a-plain-english-guide-to-javascript-prototypes/?utm_source=javascriptweekly&utm_medium=email
當我第一次學習javascript的對象模型時,我的反應時困惑。因為這是我第一次接觸基于原型的語言,是以我完完全全被原型弄得糊裡糊塗
(譯者語:在看這篇文章前,我一直困惑function的prototype和object的__proto__的差別及它們之間的關系)。我不能了解
javascript通過構造函數(function constructors)的方式來實作一種獨特的原型。我相信你們當中也有類似經曆的人。
但随着自己寫得越來越多javascript,我不僅了解了它的對象模型而且已經開始喜歡上它了。感謝javascript我發現基于原型的語言的高雅與靈活。我現在十分喜歡基于原型的語言,因為它有比基于類的語言更簡單和靈活的對性模型。
1. prototypes in javascript
大多數教程多會在直接通過講述構造函數(constructor functions)來講解javascript的對象。我并不認同這種做法,這樣隻會令到我們更困惑。是以下面我們先學習一些基礎的原型吧!
2. prototype chains(prototype inheritance)原型鍊/原型繼承
javascript的每個對象均有一個原型(prototype)。當消息(請求某個屬性的指令)到達某個對象時,javascript會嘗
試在該對象上尋找該屬性,但沒有的時候就會将消息轉發到該對象的原型并在原型上尋找該屬性,就是這樣不斷向上層原型轉發消息,直到在某個原型中找到該屬性
或消息轉發到頂層原型(object對象)。(譯者語:每個對象的原型均指向另一個對象,最頂層的原型就是object類的執行個體)

原型繼承鍊可以無限延長。但一般情況下過長的原型鍊會令人困惑且難以維護。
3.the __proto__ object
我們可以通過__proto__屬性來簡化對javascript原型的了解。但不幸的是__proto__屬性并非javascript的标準接口。是以我們不應該在生産環境中依賴該屬性。我看一看下面的代碼片段吧!
可以看到通過對象的__proto__屬性我們可以簡單、友善地設定對象的原型。
下面我們通過isprototypeof函數來判斷父、子類的關系
4. prototype lookups are dynamic(原型變化的即時性)
你可以在任何時間添加屬性到對象的原型中,然後就能馬上通過對象來擷取該屬性。(譯者語:因為正如2. prototype chains(prototype inheritance)原型鍊/原型繼承講述那樣,消息是在原型鍊傳遞并在原型中尋找該屬性,是以為原型增删改了屬性能即時反映出來)
5. new/updated properties are assigned to the object, not to the prototype(增改對象的屬性)
看代碼吧!
(譯者語:在對象中已找到了相應的屬性,那麼就不會将消息轉發到原型去)
6. object.create
(譯者語:我們甚至可以通過object.create(null)開建立一個沒有原型的對象;而使用其他方式建立的對象它的原型鍊中至少有一個object類執行個體)
當然在建立對象的時候,還可以設定該對象的屬性。
7. object.getprotype
我們可以通過object.getprototypeof來擷取對象的原型
8.constructor functions(構造函數)
構造函是javascript中用于構造原型鍊的最常用的方法。因為它是構造類型的唯一的原始方式。而很對javascript引擎對構造函數也提供了性能上的優化。
與此同時,構造函數是javascript中一個重要且容易令人疑惑的知識點。
8.1. functions as contructors
我們通過關鍵字new來建立foo函數的執行個體foo
8.2. 'this' is assigned implicitly(隐式配置設定的this)
當我們使用關鍵字new建立函數執行個體時,javascript會隐式地建立一個this對象,并在函數的最後傳回該this對象。
相當于
注意:這個隐式建立的this對象,當且僅當使用關鍵字new建立函數執行個體時出現,若不使用關鍵字new就會就會出現不可預知的問題,一般情況下為以首字母大寫的方式來命名構造函數,以提示需使用關鍵字new來調用該函數。
8.3. the 'function prototype'
每一個javascript的函數都有一個名為prototype的屬性(譯者語:這個prototype屬性與之前說__proto__一樣
會指向原型,它們之間的關系下面的内容會有所講解。因為prototype這個屬性名稱的中文就是為原型,是以為了區分下面的内容會用
“prototype屬性”來代表function的prototype屬性)
這個prototype屬性與之前說__proto__一樣會指向原型,但兩者指向的原型又有所差別,具體請看
(譯者語:這裡原文的代碼和講解有問題,據本人實踐所得,對象并沒有prototype屬性,若要通路對象的原型需要使用__proto__屬性或
object.getprototype函數;而要通路函數的原型則要通過通路prototype屬性。而上述代碼的無論foo是對象還是函數均有一方必
為undefined,比較結果鐵定為false。下面代碼片段可以證明兩者指向相同的原型:
function foo(){}
var foo = new foo();
object.getprototype(foo) === foo.prototype; // => true
且原型為foo {},該原型的原型為object {};foo{} 中有constructor屬性指向function foo(){}自身。)
__proto__和prototype屬性的關系其實很簡單,prototype屬性所指向的原型會在使用關鍵字new調用構造函數時被複制到隐
式建立的this對象的__proto__中。是以prototype屬性指向的原型有那些屬性和方法,那麼__proto__就有哪些屬性和方法。
我想大家應該已經了解了吧,轉載請标明出處:http://www.cnblogs.com/fsjohnhuang/archive/2013/03/04/2942274.html^_^!!