2013-04-13 120 views
4

我發現了一些有趣的例子。其中有鏈接到這article。 據說:Javascript函數重寫原型

Function.__proto__Function.prototype。這導致:

Function.constructor === Function 

也就是說:功能是它自己的構造!

Object instanceof Object == true. 

這是因爲:

Object.__proto__.__proto__.constructor == Object 

還要注意的是不像Object instanceof ObjectFoo instanceof Foo == false。 這是因爲:Foo不存在作爲它自己的原型鏈的構造函數。

從Mozilla開發者網絡我發現原型和構造函數都可以很容易被重寫。而且由於instanceof只是在原型鏈中檢查constructor.prototype,所以我不明白爲什麼我的代碼仍然返回false

function Foo() { } ; 
Foo.prototype = Foo 
Foo.constructor = Foo 
Foo instanceof Foo // still false 

還有一些關於原型的quetions。我做對了嗎,原型本身是一個單獨的輔助對象?這個對象就像另一個對象上的指針 - 通常是Object

回答

4

obj instanceof不尋找constructorobj.prototype,但在對象的內部__proto__屬性。

javascript中的每個對象都有一個引用對象原型的內部__proto__屬性。當使用new運算符構造對象時,該對象的內部__proto__屬性將設置爲構造函數的prototype屬性。

因此,當您說Foo instanceof Foo時,JavaScript VM將在Foo.__proto__中查找「Foo」。因爲Foo是函數,所以Foo.__proto__Function.prototype(其中Function是函數的構造函數)。

由於您實際上不能更改對象的內部__proto__屬性,因此Foo永遠不會是Foo的實例。


關於你的小問題:在javascript中,一切都是一個對象。這包括原型函數。實際上,ECMAScript 5添加了一個函數Object.createMDN),它將一個對象作爲其第一個參數,並使用第一個對象作爲其內部原型對象創建一個新對象。

+0

嗯...有人能告訴我如何把大膽__proto__成_原_? – Bart

+0

對不起,重複的答案,你是一個很好的答案。我不知道如何逃避大膽的減價,而不是將其包裝在代碼段中,就像您之前在答案中所做的那樣。 –

+0

謝謝你的回答,的確如此。我試圖改變'__proto__'和JS虛擬機顯示和對象的循環錯誤。 –

1

重要的是要記住,一個對象的實際,內部參考的原型就是原型鏈的一部分是不一樣的東西作爲對象的原型財產是很重要的。對象的內部原型設置爲其構造函數的原型屬性

我在學習這篇文章時最容易理解的文章實際上是this one

換句話說,更改對象的prototype屬性的唯一一點是該對象是否應該用作構造函數的函數。除此之外,沒有什麼神奇的,它只是一個屬性。更改prototype不會更改__proto__,並且不會影響對象的原型鏈。

因此,要通過代碼:

function Foo() {} 

Foo的構造函數實際上是在這一點上的功能,並且Function.prototype的是Foo的實際,內部原型,或者如果你願意__proto__

Foo.prototype = Foo; 

這不僅改變Foo原型財產,但不是它的內部原型。

Foo.constructor = Foo 

這實際上只設置在富constructor屬性,它什麼都不做與Foo.prototype.constructor,它不會做Foo的內部原型的構造或者,這正是instanceof檢查什麼。


試試這個代碼序列,希望這將是一個更清楚一點:

function Foo() { } ; 

(Foo.prototype != Function.prototype && Foo.__proto__ == Function.prototype); 

Foo.prototype = Foo; 

(Foo.prototype == Foo && Foo.__proto__ != Foo && Foo.__proto__ == Function.prototype); 

Foo.constructor = Foo; 

(Foo.constructor == Foo && Foo.prototype.constructor == Foo && Foo.__proto__.constructor != Foo); 
+0

感謝文章和評論,現在它看起來更加整潔。 –

+0

似乎在你上個例子中應該是'Foo.prototype.constructor == Foo' –

+0

是的,謝謝。函數的prototype.constructor始終是函數本身,除非明確更改。 –