JavaScript构造函数序言的目的是什么

What is purpose of the javascript constructor prologue?

本文关键字:是什么 构造函数 JavaScript      更新时间:2023-09-26

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

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

你能解释一下这是干什么用的吗?谢谢。

>instanceof检查对象以查看它是否可能是通过给定的构造函数构造的。该序言用于处理有人调用MyClass构造函数而不使用new的情况。这意味着您可以按照预期使用的方式使用MyClass

var c = new MyClass();

。或不new

var c = MyClass();

后一种情况下,在对MyClass的调用中,this不会被instanceof MyClass(要么是undefined[在严格模式下],要么是全局对象[在松散模式下](,所以作者知道调用者没有使用new,只是让函数通过执行return new MyClass();而不是正常的构造工作来为他们做new

有些人喜欢这样做,所以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;
}

该代码完全不会意外创建全局变量,因为如果有人在没有new的情况下调用MyClassthis.someProperty = someValue;行将抛出(因为this将被undefined(。(调用方是否使用严格模式并不重要;我们在定义MyClass构造函数的代码中使用严格模式就足够了。

当然,有些人仍然倾向于将new设为可选,在这种情况下,他们仍然需要序言。

为了避免直接调用构造器将一些变量注册到全局变量,这是JavaScript的一个著名缺陷。

function Foo() {
    // don't do prologue
    this.foo = 'foo';
}
Foo(); // direct call a constructor
console.log(window.foo) // foo, global is polluted.