简而言之:
new something2() instanceof something2 === false
相关地,如果您扩展示例以使用原型属性
Something.prototype.method = function () { };
something2.prototype.method = function () { };
你会发现在后一种情况下原型没有被继承:
typeof (new Something()).method === "function"
type (new something2()).method === "undefined"
真正的答案是你正在利用完全不同的底层机制。调用 withnew
调用[[Construct]]机制,该机制涉及根据.prototype
构造函数的属性设置 [[Prototype]] 属性。
但是在 [[Construct]] 算法的第 8--10 步中发生了一件有趣的事情:在设置一个新的空对象,然后附加它的 [[Prototype]] 之后,它对实际对象执行 [[Call]]构造函数,使用这个新的空加原型对象作为this
. 然后,在第 9 步中,如果结果证明该构造函数返回了一些东西——它会丢弃this
它花费所有时间设置的原型绑定、作为对象传递的对象!
注意:您可以通过以下方式访问对象的 [[Prototype]](与构造函数的 不同.prototype
)Object.getPrototypeOf
:
Object.getPrototypeOf(new Something()) === Something.prototype // steps 5 & 6
Object.getPrototypeOf(new something2()) === Object.prototype // default
回答一些元问题:
- 不,不要大写
something2
,因为它是工厂函数而不是构造函数。如果某些东西是大写的,那么它应该具有构造函数语义,例如new A() instanceof A
.
- 如果您担心破坏全局命名空间的危险,您应该开始使用严格模式,将其放在
"use strict";
文件的顶部。严格模式的许多不错的清理之一是this
默认为undefined
,而不是全局对象,因此例如调用构造函数而不使用new
将导致构造函数尝试将属性附加到的那一刻出错undefined
。
- 工厂函数(又名“闭包模式”)通常是构造函数和类的合理替代品,只要您 (a) 不使用继承;(b) 不构造该对象的太多实例。后者是因为,在闭包模式中,您将每个方法的新实例附加到每个新创建的对象,这对内存使用不利。IMO 闭包模式的最大收益是使用“私有”变量的能力(这是一件好事,不要让任何人告诉你:P)。