使用“new”运算符创建对象时,我们可以省略括号吗?

时间:2010-06-14 04:22:41

标签: javascript new-operator

我见过以这种方式创建的对象:

const obj = new Foo;

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

const obj = new Foo();

创建对象的前一种方式是否在ECMAScript标准中有效并定义?前一种创建对象的方式和后一种方法之间是否存在差异?一个人比另一个更受欢迎吗?

6 个答案:

答案 0 :(得分:217)

引用David Flanagan 1

  

作为一种特殊情况,对于new运算符,JavaScript通过允许在函数调用中没有参数时省略括号来简化语法。以下是使用new运算符的一些示例:

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

...

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

此外,如果省略括号,JSLint可能会伤害您的感受。它报告Missing '()' invoking a constructor,并且该工具似乎没有选项可以容忍括号内的遗漏。


1 David Flanagan:JavaScript the Definitive Guide: 4th Edition(第75页)

答案 1 :(得分:58)

两者之间存在差异:

  • new Date().toString()完美无缺,并返回当前日期
  • new Date.toString()抛出" TypeError:Date.toString不是构造函数"

这是因为new Date()new Date具有不同的优先级。根据{{​​3}}我们感兴趣的JavaScript运算符优先级表的部分看起来像:

╔════════════╦═════════════════════════════╦═══════════════╦═════════════╗
║ Precedence ║        Operator type        ║ Associativity ║  Operators  ║
╠════════════╬═════════════════════════════╬═══════════════╬═════════════╣
║     18     ║ Member Access               ║ left-to-right ║ … . …       ║
║            ║ Computed Member Access      ║ left-to-right ║  … [ … ]    ║
║            ║ new (with argument list)    ║ n/a           ║ new … ( … ) ║
╠════════════╬═════════════════════════════╬═══════════════╬═════════════╣
║     17     ║ Function Call               ║ left-to-right ║ … ( … )     ║
║            ║ new (without argument list) ║ right-to-left ║ new …       ║
╚════════════╩═════════════════════════════╩═══════════════╩═════════════╝

从下表中可以看出:

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

    new Foo().运算符

    具有相同的优先级

    new Foo的优先级低于.运算符

    new Date().toString()完美无缺,因为它的评估结果为(new Date()).toString()

    new Date.toString()抛出" TypeError:Date.toString不是构造函数"因为.的优先级高于new Date(高于"函数调用"),表达式的评估结果为(new (Date.toString))()

    可以将相同的逻辑应用于… [ … ]运算符。

  2. new Foo具有从右到左的关联性以及new Foo()"关联性"不适用。我认为在实践中它并没有任何区别。有关其他信息,请参阅MDN SO问题

  3.   

    是一个优先于另一个吗?

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

答案 2 :(得分:14)

当您使用“new”运算符时,我认为没有任何区别。要小心养成这种习惯,因为这两行代码并不相同:

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

答案 3 :(得分:13)

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

答案 4 :(得分:6)

https://people.mozilla.org/~jorendorff/es6-draft.html#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

答案 5 :(得分:3)

两者之间没有区别。