我见过以这种方式创建的对象:
const obj = new Foo;
但是我认为在创建对象时括号不是可选的:
const obj = new Foo();
前一种创建对象的方式是否有效并在 ECMAScript 标准中定义?前者和后者创建对象的方式有什么区别吗?一个比另一个更受欢迎吗?
我见过以这种方式创建的对象:
const obj = new Foo;
但是我认为在创建对象时括号不是可选的:
const obj = new Foo();
前一种创建对象的方式是否有效并在 ECMAScript 标准中定义?前者和后者创建对象的方式有什么区别吗?一个比另一个更受欢迎吗?
引用大卫弗拉纳根1:
作为一种特殊情况,
new
仅对于运算符,JavaScript 通过允许在函数调用中没有参数时省略括号来简化语法。以下是使用new
运算符的一些示例:o = new Object; // Optional parenthesis omitted here d = new Date(); ...
就个人而言,我总是使用括号,即使构造函数没有参数。
此外,如果省略括号,JSLint可能会伤害您的感受。它报告Missing '()' invoking a constructor
,并且该工具似乎没有选项可以容忍括号省略。
1 David Flanagan:JavaScript 权威指南:第 4 版(第 75 页)
两者有以下区别:
new Date().toString()
完美运行并返回当前日期new Date.toString()
抛出“类型错误:Date.toString 不是构造函数”它发生是因为new Date()
和new Date
具有不同的优先级。根据MDN,我们感兴趣的 JavaScript 运算符优先级表的部分如下所示:
优先级 | 操作员类型 | 关联性 | 运营商 |
---|---|---|---|
18 | 成员访问 计算成员访问 new (带参数列表) |
从左到右 从左到右 不 适用 |
… . … … [ … ] new … ( … ) |
17 | 函数调用new (无参数列表) |
从左到右 从右到左 |
… ( … ) new … |
从这张表可以看出:
new Foo()
优先级高于 new Foo
new Foo()
与.
运算符具有相同的优先级
new Foo
具有比.
运算符低一级的优先级
new Date().toString()
工作完美,因为它评估为 (new Date()).toString()
new Date.toString()
抛出“ TypeError: Date.toString is not a constructor ”因为.
优先级高于new Date
(并且高于“函数调用”)并且表达式计算为(new (Date.toString))()
相同的逻辑可以应用于… [ … ]
运算符。
new Foo
具有从右到左的关联性,new Foo()
“关联性”不适用。我认为在实践中它没有任何区别。有关其他信息,请参阅此SO 问题
一个比另一个更受欢迎吗?
知道所有这些,可以假设这new Foo()
是首选。
如果您没有要传递的参数,则括号是可选的。省略它们只是语法糖。
当您使用“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://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