我见过以这种方式创建的对象:
const obj = new Foo;
但我认为在创建对象时括号不是可选的:
const obj = new Foo();
创建对象的前一种方式是否在ECMAScript标准中有效并定义?前一种创建对象的方式和后一种方法之间是否存在差异?一个人比另一个更受欢迎吗?
答案 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 … ║
╚════════════╩═════════════════════════════╩═══════════════╩═════════════╝
从下表中可以看出:
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))()
可以将相同的逻辑应用于… [ … ]
运算符。
new Foo
具有从右到左的关联性以及new Foo()
"关联性"不适用。我认为在实践中它并没有任何区别。有关其他信息,请参阅MDN SO问题
是一个优先于另一个吗?
了解所有这些,可以假设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)
两者之间没有区别。