javascript
Javascript Prototypes之旅(A Plain English Guide to JavaScript Prototypes译文)
英文原文地址: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__的區(qū)別及它們之間的關系)。我不能理解JavaScript通過構(gòu)造函數(shù)(function constructors)的方式來實現(xiàn)一種獨特的原型。我相信你們當中也有類似經(jīng)歷的人。
但隨著自己寫得越來越多javascript,我不僅理解了它的對象模型而且已經(jīng)開始喜歡上它了。感謝Javascript我發(fā)現(xiàn)基于原型的語言的高雅與靈活。我現(xiàn)在十分喜歡基于原型的語言,因為它有比基于類的語言更簡單和靈活的對性模型。
1. Prototypes in Javascript
大多數(shù)教程多會在直接通過講述構(gòu)造函數(shù)(constructor functions)來講解Javascript的對象。我并不認同這種做法,這樣只會令到我們更困惑。所以下面我們先學習一些基礎的原型吧!
2. Prototype chains(prototype inheritance)原型鏈/原型繼承
Javascript的每個對象均有一個原型(prototype)。當消息(請求某個屬性的指令)到達某個對象時,Javascript會嘗試在該對象上尋找該屬性,但沒有的時候就會將消息轉(zhuǎn)發(fā)到該對象的原型并在原型上尋找該屬性,就是這樣不斷向上層原型轉(zhuǎn)發(fā)消息,直到在某個原型中找到該屬性或消息轉(zhuǎn)發(fā)到頂層原型(Object對象)。(譯者語:每個對象的原型均指向另一個對象,最頂層的原型就是Object類的實例)
原型繼承鏈可以無限延長。但一般情況下過長的原型鏈會令人困惑且難以維護。
?
3.The __proto__ object
我們可以通過__proto__屬性來簡化對Javascript原型的理解。但不幸的是__proto__屬性并非Javascript的標準接口。所以我們不應該在生產(chǎn)環(huán)境中依賴該屬性。我看一看下面的代碼片段吧!
可以看到通過對象的__proto__屬性我們可以簡單、方便地設置對象的原型。
下面我們通過isPrototypeof函數(shù)來判斷父、子類的關系
?
4. Prototype lookups are dynamic(原型變化的即時性)
你可以在任何時間添加屬性到對象的原型中,然后就能馬上通過對象來獲取該屬性。(譯者語:因為正如2. Prototype chains(prototype inheritance)原型鏈/原型繼承講述那樣,消息是在原型鏈傳遞并在原型中尋找該屬性,所以為原型增刪改了屬性能即時反映出來)
?
5. New/updated properties are assigned to the ?object, not to the prototype(增改對象的屬性)
看代碼吧!
(譯者語:在對象中已找到了相應的屬性,那么就不會將消息轉(zhuǎn)發(fā)到原型去)
?
6. Object.create
前面已經(jīng)說過__proto__屬性并非設置原型的標準方法。下面我們使用Object.create方法來創(chuàng)建對象并指定該對象的原型。該方法在ES5中可用,但老的瀏覽器和JS引擎要通過es5-hhim來使用了。
(譯者語:我們甚至可以通過object.create(null)開創(chuàng)建一個沒有原型的對象;而使用其他方式創(chuàng)建的對象它的原型鏈中至少有一個Object類實例)
當然在創(chuàng)建對象的時候,還可以設置該對象的屬性。
這里打算展開對象屬性設置方面的幾個特性的使用方法,大家可以參考相關的文檔?here。
7. Object.getProtype
我們可以通過Object.getPrototypeOf來獲取對象的原型
8.Constructor Functions(構(gòu)造函數(shù))
構(gòu)造函是javascript中用于構(gòu)造原型鏈的最常用的方法。因為它是構(gòu)造類型的唯一的原始方式。而很對javascript引擎對構(gòu)造函數(shù)也提供了性能上的優(yōu)化。
與此同時,構(gòu)造函數(shù)是javascript中一個重要且容易令人疑惑的知識點。
8.1. Functions as contructors
我們通過關鍵字new來創(chuàng)建Foo函數(shù)的實例foo
8.2. 'this' is assigned implicitly(隱式分配的this)
當我們使用關鍵字new創(chuàng)建函數(shù)實例時,Javascript會隱式地創(chuàng)建一個this對象,并在函數(shù)的最后返回該this對象。
相當于
注意:這個隱式創(chuàng)建的this對象,當且僅當使用關鍵字new創(chuàng)建函數(shù)實例時出現(xiàn),若不使用關鍵字new就會就會出現(xiàn)不可預知的問題,一般情況下為以首字母大寫的方式來命名構(gòu)造函數(shù),以提示需使用關鍵字new來調(diào)用該函數(shù)。
8.3. The 'function prototype'
每一個Javascript的函數(shù)都有一個名為prototype的屬性(譯者語:這個prototype屬性與之前說__proto__一樣會指向原型,它們之間的關系下面的內(nèi)容會有所講解。因為prototype這個屬性名稱的中文就是為原型,所以為了區(qū)分下面的內(nèi)容會用“prototype屬性”來代表function的prototype屬性)
這個prototype屬性與之前說__proto__一樣會指向原型,但兩者指向的原型又有所區(qū)別,具體請看
(譯者語:這里原文的代碼和講解有問題,據(jù)本人實踐所得,對象并沒有prototype屬性,若要訪問對象的原型需要使用__proto__屬性或Object.getPrototype函數(shù);而要訪問函數(shù)的原型則要通過訪問prototype屬性。而上述代碼的無論foo是對象還是函數(shù)均有一方必為undefined,比較結(jié)果鐵定為false。下面代碼片段可以證明兩者指向相同的原型:
function Foo(){}
var foo = new Foo();
Object.getPrototype(foo) === Foo.prototype; // => true
且原型為Foo {},該原型的原型為Object {};Foo{} 中有constructor屬性指向function Foo(){}自身。)
__proto__和prototype屬性的關系其實很簡單,prototype屬性所指向的原型會在使用關鍵字new調(diào)用構(gòu)造函數(shù)時被復制到隱式創(chuàng)建的this對象的__proto__中。所以prototype屬性指向的原型有那些屬性和方法,那么__proto__就有哪些屬性和方法。
我想大家應該已經(jīng)理解了吧,轉(zhuǎn)載請標明出處:http://www.cnblogs.com/fsjohnhuang/archive/2013/03/04/2942274.html^_^!!
總結(jié)
以上是生活随笔為你收集整理的Javascript Prototypes之旅(A Plain English Guide to JavaScript Prototypes译文)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP正则表达式入门教程[转]
- 下一篇: SAP ABAP 点滴记录