我见过这样创建对象:

const obj = new Foo;

但我认为括号在创建对象时是不可选的:

const obj = new Foo();

前一种创建对象的方式是否有效并在ECMAScript标准中定义?前一种创建对象的方式和后一种创建对象的方式有什么区别吗?两者孰优孰劣?


当前回答

两者之间有区别:

new Date().toString()工作正常,返回当前日期 new Date. tostring()抛出“TypeError: Date”。toString不是构造函数

这是因为new Date()和new Date具有不同的优先级。根据MDN,我们感兴趣的JavaScript操作符优先级表部分如下所示:

Precedence Operator type Associativity Operators
18 Member Access
Computed Member Access
new (with argument list)
left-to-right
left-to-right
n/a
… . …
… [ … ]
new … ( … )
17 Function Call
new (without argument list)
left-to-right
right-to-left
… ( … )
new …

从该表可以看出:

new Foo() has higher precedence than new Foo new Foo() has the same precedence as . operator new Foo has one level lower precedence than the . operator new Date().toString() works perfectly because it evaluates as (new Date()).toString() new Date.toString() throws "TypeError: Date.toString is not a constructor" because . has higher precedence than new Date (and higher then "Function Call") and the expression evaluates as (new (Date.toString))() The same logic can be applied to … [ … ] operator. new Foo has right-to-left associativity and for new Foo() "associativity" isn't applicable. I think in practice it doesn't make any difference. For additional information see this SO question


两者孰优孰劣?

知道了所有这些,可以假设首选new Foo()。

其他回答

引用大卫·弗拉纳根的话:

作为一种特殊情况,仅对于new操作符,JavaScript允许在函数调用中没有参数时省略圆括号,从而简化了语法。下面是一些使用new操作符的例子: o = new对象;//此处省略可选括号 d = new Date(); ...

就我个人而言,我总是使用圆括号,即使构造函数没有参数。

此外,如果省略括号,JSLint可能会伤害您的感情。它报告Missing '()'调用了一个构造函数,并且似乎没有一个选项可以让工具容忍圆括号遗漏。


1 David Flanagan: JavaScript权威指南:第4版(第75页)

如果没有要传递的参数,则括号是可选的。省略它们只是语法上的糖。

两者之间没有区别。

我不认为当你使用“new”操作符时有任何区别。要小心养成这种习惯,因为这两行代码是不一样的:

var someVar = myFunc; // this assigns the function myFunc to someVar
var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar

https://262.ecma-international.org/6.0/#sec-new-operator-runtime-semantics-evaluation

下面是ES6规范中定义这两个变体如何操作的部分。无括号变量传递一个空参数列表。

有趣的是,这两种形式有不同的语法含义。当您试图访问结果的成员时,就会出现这种情况。

new Array.length // fails because Array.length is the number 1, not a constructor
new Array().length // 0