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

Call function directly after constructor "new"

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

 (new Date()).toString()

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

这种方式实例化新对象后可以立即使用函数调用吗?

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

In many languages, to invoke some function directly on new instance I need to wrap it into braces Is it allowed to use function call immediately after instantiating new object in this way?

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

但是 operator precedence 来拯救了。

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

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

It looks like new keyword is optional sometimes. How is this interpreted by JS engine?

完全没有。这不是 JS 功能,这是实现这些 functions/classes/constructors

的一个怪癖

有点像这些实现:

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());

再次提防。由于添加了 security/failsafety,您无法使用新的 class 关键字实现类似的功能。它添加了 (hidden) 代码以确保这些构造函数始终使用 new 关键字调用,否则构造函数会抛出错误。

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

EMCAScript spec

The Date constructor is the %Date% intrinsic object and the initial value of the Date property of the global object. When called as a constructor it creates and initializes a new Date object. When Date is called as a function rather than as a constructor, it returns a String representing the current time (UTC).

// with new
const a = new Date();
console.log(typeof a); // object
console.log(a instanceof Date); // true
console.log(a.toString()); // date formatted string

// without new
const b = Date();
console.log(typeof b); // string
console.log(b instanceof Date); // false
console.log(b.toString()); // date formatted string

如您所见,Date 的这种行为在语言规范中有明确描述,它与 new 是可选的无关。 只需通读以下热门问题,您就可以发现很多关于 new 的信息:https://whosebug.com/search?q=javascript+new+keyword

最后,您可以立即使用新创建的对象。不需要用括号括起来。