我见过这样创建对象:
const obj = new Foo;
但我认为括号在创建对象时是不可选的:
const obj = new Foo();
前一种创建对象的方式是否有效并在ECMAScript标准中定义?前一种创建对象的方式和后一种创建对象的方式有什么区别吗?两者孰优孰劣?
我见过这样创建对象:
const obj = new Foo;
但我认为括号在创建对象时是不可选的:
const obj = new Foo();
前一种创建对象的方式是否有效并在ECMAScript标准中定义?前一种创建对象的方式和后一种创建对象的方式有什么区别吗?两者孰优孰劣?
当前回答
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()抛出“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”操作符时有任何区别。要小心养成这种习惯,因为这两行代码是不一样的:
var someVar = myFunc; // this assigns the function myFunc to someVar
var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar
引用大卫·弗拉纳根的话:
作为一种特殊情况,仅对于new操作符,JavaScript允许在函数调用中没有参数时省略圆括号,从而简化了语法。下面是一些使用new操作符的例子: o = new对象;//此处省略可选括号 d = new Date(); ...
就我个人而言,我总是使用圆括号,即使构造函数没有参数。
此外,如果省略括号,JSLint可能会伤害您的感情。它报告Missing '()'调用了一个构造函数,并且似乎没有一个选项可以让工具容忍圆括号遗漏。
1 David Flanagan: JavaScript权威指南:第4版(第75页)