在构造函数“new”之后直接调用函数

ANT*_*ARA 3 javascript internals

在许多语言中,要直接在新实例上调用某些函数,我需要将其包装在大括号中:

 (new Date()).toString()
Run Code Online (Sandbox Code Playgroud)

在 JS 中new Date().toString()Date().toString()给出相同的结果。

是否允许在以这种方式实例化新对象后立即使用函数调用?

看起来new关键字有时是可选的。JS引擎如何解释这个?

Tho*_*mas 5

在许多语言中,要直接在新实例上调用某些函数,我需要将其包装在大括号中 是否允许在以这种方式实例化新对象后立即使用函数调用?

我认为这里的问题是潜在的歧义。虽然(new Date()).toString()很清楚,new Date().toString()(理论上)可能意味着(new Date()).toString()new (Date().toString)()

但这里是运营商优先救援。

new (with argument list)操作符比函数调用一个更高的优先级。因此,执行顺序与必须执行这些数学运算的顺序new Date().toString()一样清晰(至少对引擎而言)2 + 3 * 4

但是要注意,在 JS 中你也可以new Date;不用括号来写,而且这个运算符new (without argument list)的优先级低于函数调用。所以new Date.toString()被解释为new (Date.toString)()并且你得到一个toString()不是构造函数的错误。

看起来 new 关键字有时是可选的。JS引擎如何解释这个?

一点也不。这不是 JS 特性,这是这些函数/类/构造函数的实现中的一个怪癖

有点像这些实现:

function Foo(){
    if(!(this instanceof Foo)) 
        return new Foo();

    this.foo = 42;
}

//or something like
function Bar(){
    return Object.create(Bar.prototype, {
        bar: { value: 42 }
    });
}

console.log(new Foo(), Foo());
console.log(new Bar(), Bar());
Run Code Online (Sandbox Code Playgroud)

再次小心。由于增加了安全性/故障安全性,您无法使用 newclass关键字实现类似的功能。它添加(隐藏)代码以确保始终使用new关键字调用这些构造函数,否则构造函数会引发错误。

编辑: 例如 Array 构造函数的工作方式如上所述,但看起来(如Freeman Lambdas answer所指出的)Date 构造函数具有(由规范定义)两个不同的返回值,具体取决于您将其称为函数还是作为构造函数。