我经常在许多node.js / javascript源中遇到以下构造函数序言。
function MyClass () {
// prologue
if (!(this instanceof MyClass)) {
return new MyClass();
}
// do actual constructor logic
}
你能解释一下这是为了什么吗?感谢。
答案 0 :(得分:2)
instanceof
检查一个对象,看它是否可能是通过给定的构造函数构造的。那个序言是为了处理有人在不使用MyClass
的情况下调用new
构造函数的情况。这意味着您可以按照其使用方式使用MyClass
:
var c = new MyClass();
...或没有new
:
var c = MyClass();
在后一种情况下,在MyClass
的来电中,this
不会成为instanceof MyClass
(它是undefined
[严格来说]模式]或全局对象[在松散模式下]),因此作者知道调用者没有使用new
,只是让函数通过执行new
来执行return new MyClass();
{1}}而不是正常的建筑工作。
有些人喜欢这样做,new
是可选的,其他人认为new
这样的选项是个不错的主意。在严格模式之前的糟糕时期,另一种方法是检测调用者未能使用new
并抛出异常:
// Old pre-strict code
if (!(this instanceof MyClass)) {
throw "MyClass is a constructor, use new";
}
如果您不这样做,并且您正在使用宽松模式,并且您将属性分配给this
,那么您将为全局对象分配属性(这些属性是全局的)变量),这是一个坏主意(tm)。
但现在我们有严格的模式,这是使用它的众多原因之一:
"use strict"; // At the top of the file or `script` block
function MyClass() {
// No need for the check anymore
this.someProperty = someValue;
}
该代码完全可以避免意外创建全局变量的问题,因为如果有人在没有this.someProperty = someValue;
的情况下调用MyClass
,new
行将会抛出(因为this
将是undefined
)。 (并且调用者是否使用严格模式并不重要;我们在定义MyClass
构造函数的代码中使用严格模式就足够了。)
有些人仍然希望new
可选,当然,在这种情况下,他们仍然需要序言。
答案 1 :(得分:1)
为了避免直接调用构造函数将一些变量注册到全局,这是一个着名的JavaScript缺陷。
function Foo() {
// don't do prologue
this.foo = 'foo';
}
Foo(); // direct call a constructor
console.log(window.foo) // foo, global is polluted.