2013-01-04 80 views
4

我看到JavaScript Patterns書斯托揚斯特凡(編輯,以去除多餘的脂肪)下面的代碼:當函數重新定義時,原型會發生什麼?

function Universe() { 
    var instance = this; 
    Universe = function() { 
     return instance; 
    } 
} 

Universe.prototype.nothing = true; 
var uni = new Universe(); 
Universe.prototype.everything = true; 
var uni2 = new Universe(); 

uni.nothing;  // true 
uni2.nothing; // true, but I was expecting undefined 
uni.everything; // undefined 
uni2.everything; // undefined, but I was expecting true 

我期待nothing被分配到原函數的原型,everything被分配到封閉的原型(因爲第二個任務在重新定義後發生)。然而,輸出顯示有些奇怪的事情正在發生,而這本書並沒有解釋它。我還注意到:

  1. Universe.prototype確實在函數重新定義後指向不同的對象,如我所料。
  2. 重新定義後創建的其他實例仍將原始原型對象作爲它們的__proto__。這是我不明白的。

請問誰能解釋一下?

回答

3

uniuni2是相同的對象,因爲在Universe函數的兩個版本中都返回instance的值。

下面是相同的代碼,但沒有instance從返回的重新定義Universehttp://jsfiddle.net/nmaBn/

+0

當然!我怎麼會錯過!我專注於原型和重新定義,並忘記了返回值(實際上這就是這個例子的全部內容)。 – bfavaretto

+0

@bfavaretto我錯過了,不得不突破jsFiddle ......但是,我認爲你發現了這個單例模式的實現中的一些真正的問題:原型鏈被交換,正如有人在評論中指出的那樣, instanceof'操作符失敗。如果對原始的'Universe'函數的引用存儲了一些,則會出現另一個潛在的問題。這些顯示在[this jsFiddle](http://jsfiddle.net/nmaBn/9/)中。一些修改解決了它們,但是它們增加了複雜性:[demo](http://jsfiddle.net/nmaBn/10/) – tiffon

+0

我想底線是(並且必須提及那本書提到這一點) :在js中創建單例最簡單的方法就是使用對象文字。 – bfavaretto

5

這是一個單例模式。宇宙第一次創建時,宇宙符號被重新定義。 (它仍然存在處於一箇中間的,雖然:實例具有一定的參考吧__proto__在非嚴格模式,例如。)

新宇宙符號不是實際上是一個構造函數,它只是返回第一個創建的實例。第二次調用中的new關鍵字創建了一個新的實例,並以第二個Universe爲原型,但新函數只是忽略它並返回存儲的第一個實例。

+0

謝謝你,因爲我評論上面我太專注於代碼的其他方面,並錯過了什麼存在的必要「細節」回。 D'哦! – bfavaretto

相關問題