在使用"new&quot创建对象时,可以省略括号吗?运营商吗?

我见过这样创建对象:

const obj = new Foo;

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

const obj = new Foo();

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

27589 次浏览

引用大卫·弗拉纳根1:

作为一种特殊情况,仅对于new操作符,JavaScript通过允许省略括号来简化语法,如果函数调用中没有参数。下面是一些使用new操作符的例子:

o = new Object;  // Optional parenthesis omitted here
d = new Date();


...

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

此外,如果省略括号,JSLint可能会伤害你的感情。它报告Missing '()' invoking a constructor,并且似乎没有一个选项可以让工具容忍省略圆括号。


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

两者之间有区别:

  • new Date().toString()工作正常,返回当前日期
  • new Date.toString()抛出"

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

优先级 符类型 结合性 运营商
18 成员访问
计算成员访问
new(带参数列表)
从左到右
从左到右
n/a
… . …
… [ … ]
new … ( … )
17 函数调用
new(不带参数列表)
从左到右
从右到左
… ( … )
new …

从该表可以看出:

  1. new Foo()优先级高于new Foo

    new Foo().操作符具有相同的优先级

    new Foo的优先级比.操作符低一级

    new Date().toString()工作得很好,因为它的值是(new Date()).toString()

    new Date.toString()抛出"因为.的优先级高于new Date(并且高于"Function Call"),表达式的计算结果为(new (Date.toString))()

    同样的逻辑也可以应用于… [ … ]操作符。

  2. new Foo具有从右到左的结合性,对于new Foo()“结合性”;不适用。我认为在实践中这没有任何区别。有关更多信息,请参阅 SO问题


两者孰优孰劣?

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