2012-02-26 171 views
3

有人可以解釋這一點嗎?構造函數和原型

function Foo() { 
    this.x = 1; 
    this.y = 2; 
} 

function FooProto() { 
    this.arrow = 1; 
    this.bow = 1; 
} 

document.writeln(Foo.prototype); // [object Object] 
document.writeln(Foo.prototype.constructor); // function Foo() { x =1; y=2; } 

我的理解是:Foo.prototype是一個Object,它的構造函數屬性是Function Foo。 。富[[原型]]是Function.prototype的

obj = new Foo; 
document.writeln(obj.constructor); // function Foo() { x =1; y=2; } 
document.writeln(obj.constructor.prototype); // [object Object] 

Foo.prototype = FooProto; 

document.writeln(Foo.prototype); // function FooProto() { arrow = 1; bow = 2; } 
document.writeln(Foo.prototype.constructor); // function Function() { [native code] } 

問題1:你是怎麼用[[原型]]發生在這裏的擡頭。如果有人能向我解釋這一點,我將不勝感激。

document.writeln(obj.constructor); // function Foo() { x =1; y=2; } .. no change 
document.writeln(obj.constructor.prototype); // function FooProto() { arrow = 1; bow = 2; } 

anotherObj = new Foo; 
document.writeln(anotherObj.constructor); // function Function() { [native code] } 
document.writeln(anotherObj.constructor.prototype); // function Empty() {} 

問題2:與問題1相同的問題。Javascript解釋器如何執行查找?

回答

5

在解釋基於原型的代碼時,使用Object.create來解釋東西要簡單得多。 Object.create是接收原型對象,並創建一個具有原型對象作爲其[[原型]]

當一個對象查找的屬性是這樣工作的一個新的實例對象的函數:

每對象在其內部具有自己的和不可變的[[prototype]]屬性。這個屬性是祕密和隱藏的,除非你在Firefox中,你可以通過__proto__得到它。

讀取屬性,我們首先在對象本身中搜索它,如果我們沒有找到它,我們遞歸搜索對象的[[prototype]]。

一個屬性,我們總是寫一個自己的屬性(我們從不改變[[原型]],即使它也有我們設置的屬性。

proto = {a:1}; 
child1 = Object.create(proto); 
child2 = Object.create(proto); 

child1.a = 2; 

console.log(proto.a); //1 
console.log(child1.a); //2 
console.log(child2.a); //1 

當創建一個功能

每當我們在JavaScript中創建一個函數對象,它帶有已經填充到prototype屬性。這是prototype對象(從Object.prototype中繼承),並有constructor屬性設置爲相應的功能。

當實例化使用函數構造(新的Foo)

新對象與功能prototype作爲其創建[[原型]和運行該功能對象O到初始化它的對象。


  1. 我不真的想解釋什麼是在第一種情況下怎麼回事,因爲 Foo.prototype = FooProto;部分並沒有真正意義,並可能不是你想要做的(記住,原型是什麼應該是對象,而不是函數)

  2. 至於第二種情況,更改構造函數的prototype屬性只會影響將來的實例(anotherObj)。已經創建的對象的[[prototype]]屬性是祕密和不可變的,所以你不能做任何改變。

    • 注意,如果你要動態地更改原型和現有的對象(猴子補丁),你可以做到這一點寫在現有的原型對象覆蓋,而不是用新的替換它的值。
0

有是在Javascript原型的兩個概念。 (我把它作爲在語言設計一個名稱衝突。)

  1. 原型在「原型鏈」。 它是最後一個答案中提到的內部屬性。訪問它的首選方式是Object.getPrototypeOf

    var a = {}; 
    Object.getPrototypeOf(a); // Object {} 
    Object.getPrototypeOf(Object.getPrototypeOf(a)); // null, the top of prototype chain. 
    Object.getOwnPropertyNames(Object.getPrototypeOf(a)); // the methods inherited 
    
  2. 構造(我認爲實際上可以聲明每個函數)具有自己的財產「原型」。它來用於new運營商。

new操作者確實2個步驟。

  1. 首先是創建一個對象,其原型(一日一說,[[原型]])被分配爲構造器的原型(第2一個)。
  2. 其次是運行構造函數(從prototype.constructor查找),將創建的對象作爲隱含參數this

我們您的情況:

第一obj用其指定爲Foo.prototype屬性[[原型](在某些發動機)創建的。

obj.constructor === obj.__proto__.constructor === Foo.prototype.constructor === Foo 
obj.constructor.prototype === Function.prototype 

請注意構造函數也是一個Function對象。

然後您更改了Foo的原型。這改變了obj.constructor.prototype,但不是obj.constructor,它有不同的參考。 anotherObj有一個來自以下new運算符的新[[Prototype]]。

此問題已在這裏多年。以下讀者也可能會把我困惑。我recommendated新近出版的書自Axel Rauschmayer先生說到博士的JavaScript

Terminology: The Two Prototypes

相關問題