2013-01-04 112 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

相关问题