javascript构造函数序言的目的是什么?

时间:2014-12-22 09:49:19

标签: javascript node.js design-patterns constructor

我经常在许多node.js / javascript源中遇到以下构造函数序言。

function MyClass () {
    // prologue
    if (!(this instanceof MyClass)) {
        return new MyClass();
    }
    // do actual constructor logic
}

你能解释一下这是为了什么吗?感谢。

2 个答案:

答案 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;的情况下调用MyClassnew行将会抛出(因为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.