如果构造函数foo
返回一个对象,则new foo()
与直接调用函数foo()
相同。我们可以证明是这样的话通过检查ECMAScript behavior for new
:
返回调用的结果[建设]上构造 [即,构造函数]内部方法...
函数的[[Construct]]
internal method是调用函数的[[Call]]
内部方法(这只是函数的正常行为)的特殊包装。让我们来看看的[[Construct]]
看看到底这个包装的行为:
8)让结果是调用˚F [由new
调用函数]的[[呼叫]]内部属性的结果,提供obj作为this
值并提供作为参数传递给[[Construct]]的参数列表。 9)如果Type(结果)为Object,则返回结果。
10)退货obj。
在你的情况下,你的构造函数foo
返回一个对象,所以[[Construct]]
步骤9(因此,反过来,new foo()
)返回该对象。但是我们在步骤10中看到[[Construct]]
可能返回一些其他值,称为obj,这等于构造函数中的this
值。让我们倒带,看看这是所有关于:
1)让OBJ是一个新创建的原生ECMAScript的对象。
...
4)让原是参数调用 “prototype
” F的[[获取]]内部属性的值。
5)如果Type(原)是对象,则[[原型]]内部的OBJ属性设置为原。
这里,我们看到的new
真正的力量:如果构造函数没有返回一个对象(因此[[Construct]]
操作由new
推出被允许返回obj
),然后原型继承发生。 obj
(又名obj.__proto__
)的[[Prototype]]
被设置为构造函数方法的prototype
属性。这意味着如果foo
未返回对象(而是修改this
),并且设置了foo.prototype.someProp
,则从var instance = new foo()
返回的实例将有权访问instance.someProp
。
因此,编写代码以不同的方式可能是:
var foo = function() { };
foo.prototype.setA = function(a) { this.a = a; };
foo.prototype.setA = function(a) { console.log(this.a); };
在这种情况下,产生new foo()
一个对象的原型链包括foo.prototype
,而foo()
没有。这有利于降低内存使用量:这里的所有foo
实例共享通用原型方法,而不是让每个实例都具有自己独立的功能。
相关:[构造函数VS厂功能(http://stackoverflow.com/questions/8698726/constructor-function-vs-factory-functions) –
我认为它与此相关http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript –
@ 3506238:OP已阅读。 –