2013-08-23 37 views
2

閱讀本文件後: http://es5.github.io/#x4.2.1爲什麼函數同時具有隱式和顯式原型引用,並且可以設置隱式引用?

我是通過CF兩個原型引用混淆,並且被這句話:

在CFP命名CFP1酒店被CF1共享,CF2,CF3, CF4和CF5 (而不是由CF)

許多關於JavaScript中的文獻指出,函數是第一類對象,因此我希望能夠設置像他們的隱含原型參考Ø可以實現原型繼承(聲明:我實際上並不知道我會使用這個繼承,但是我想知道是否有可能)。我可以在函數上設置這個隱式原型嗎,還是一直指向Function.prototype(我假設這是默認的)。爲什麼Function有明確的和隱含的原型?在Javascript中,還有其他類型是否有明確的和隱含的原型引用,或者在這方面是函數唯一的嗎?

+1

好的,我完全重寫了我的答案,試圖專注於我相信你錯過的東西。很難決定什麼可以放棄,但詳細說明一切都需要太多空間和時間。我希望新的答案有幫助! – bfavaretto

+0

@bfavaretto謝謝!現在閱讀,並會留下你的答案的任何反饋。 –

回答

4

考慮從規範中的圖,它下面的代碼,它試圖重現這是怎麼回事:

enter image description here

function CF() {};   // the constructor 
CF.P1 = 'foo';    // P1 is an own property of the constructor; P2 is the same 
var CFp = { CRP1: 'bar' }; // for now, just an object, with a CRP1 property 
CF.prototype = CFp   // set CFp as the 'explicit prototype property' of CF; 
          // only constructors have such a property 
var cf1 = new CF();   // an instance; 
var cf2 = new CF();   // another instance; cf3..cf5 are constructed the same way 
Object.getPrototypeOf(cf1); // CFp; this is the 'implicit prototype link' from cf1 to CFp; 
          // put another way, CFp became the [[Prototype]] of cf1 

你說你被這句話迷惑:命名屬性CFP中的CFP1由cf1,cf2,cf3,cf4和cf5(但不由CF)共享。試想一下:

cf1.CRP1; // 'bar' - found on CFp through cf1 
cf2.CRP1; // 'bar' - found on CFp through cf2 
CF.CRP1; // undefined 

那麼,這句話意味着你可以從cf1..cf5訪問CRP1的內容,而不是從構造CF(記住,函數/構造函數對象也一樣,因此它們可以有屬性)。這是因爲CFpCRP1的「所有者」)不是CF[[Prototype]],它只是CF.prototype屬性指向的值。 prototype屬性只存在於函數對象中,並且僅用於定義調用創建的實例的[[Prototype]]作爲構造函數調用(如在new CF()中)。 [[Prototype]]prototype被認爲是「原型」的事實是造成極大困惑的原因 - 也許是令你感到困惑的一部分;希望現在不那麼困惑。考慮到這一點,我會盡量簡短回答你的其他問題。

大部分有關Javascript的文獻指出,函數是第一類對象,因此我希望能夠像對象一樣設置其隱式原型引用以實現原型繼承[...]。

在ES5沒有辦法直接設置隱含原型參考(或[[Prototype]])現有的對象,除了非標準__proto__屬性。你可以做的是創建新的對象與給定[[Prototype]]。您可以使用var obj = new ConstructorFunction()來執行此操作,其中[[Prototype]]objConstructorFunction.prototypevar obj = Object.create(someOtherObj),其中[[Prototype]]objsomeOtherObj。該語言的更高版本引入了Object.setPrototypeOf來做到這一點,但出於性能方面的考慮,它的使用是不鼓勵的。

我可以在函數上設置這個隱式原型,或者它會一直指向Function.prototype(我假設這是默認值)。

是的,用__proto__Object.setPrototypeOf。但通常你不應該。

爲什麼函數有明確的和隱含的原型?在Javascript中,還有其他類型是否有明確的和隱含的原型引用,或者在這方面是函數唯一的嗎?

Function(下稱「Function構造函數」)僅僅是一個函數,並作爲任何其它函數它有一個prototype屬性;它也是一個對象,並且(幾乎)任何其他對象都具有一個對象[[Prototype]]。還有其他類型的標準構造函數,如ObjectStringArray,Boolean,Number。它們都是功能,並且有一個prototype和一個[[Prototype]]

+0

還有一些需要關注,但我的第一個問題是關於:「//將CFp設置爲CF的'顯式原型屬性';只有構造函數具有這樣的屬性。」我的理解是,JS沒有明確的方法來區分構造函數和標準函數,這就是爲什麼構造函數按照慣例大寫的原因。是否所有的函數都有一個明確的原型屬性,但是它通常不用於非構造函數? –

+0

是的,確切!所有函數都是(潛在的)構造函數,它們都具有.prototype屬性。 – bfavaretto

+0

好的,最後一點 - 函數類型的隱式[[Prototype]]是否默認爲Function.prototype,修改Function.prototype是否會影響所有函數?如果是這樣的話,我認爲函數實際上可以通過原型繼承來擴展,但是所有函數實例必須以相同的方式擴展(例如,不存在「原型函數實例」)。如果我在屠殺術語,請道歉! –

相關問題