我曾经看到过通过这种方式创建对象:
const obj = new Foo;
但是我认为在创建对象时,括号是不可选的:
const obj = new Foo();
使用之前的创建对象方式是否在ECMAScript标准中有效和定义?之前的创建对象方式和后来的方式有什么区别?是否有一种方法比另一种更可取?
我曾经看到过通过这种方式创建对象:
const obj = new Foo;
但是我认为在创建对象时,括号是不可选的:
const obj = new Foo();
使用之前的创建对象方式是否在ECMAScript标准中有效和定义?之前的创建对象方式和后来的方式有什么区别?是否有一种方法比另一种更可取?
引用David Flanagan1的话:
作为一个特例,仅适用于
new
操作符的情况下,JavaScript简化了语法,如果函数调用中没有参数,括号可以省略。以下是一些使用new
操作符的示例:
o = new Object; // Optional parenthesis omitted here
d = new Date();
...
个人上,即使构造函数不需要参数,我也会始终使用括号。new Object.func()
不等同于new Object().func()
。通过始终包括括号,可以消除犯这种错误的可能性。 - nmclean(new Object).func()
。但是我认为使用额外的括号和额外的等号,例如==
与===
,是不学习你的语言的借口。 - Jean Vincent这两者之间存在差异:
new Date().toString()
可以正常工作并返回当前日期new Date.toString()
会抛出“TypeError: 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不是构造函数”,因为.
具有比new Date
(以及比“函数调用”更高的优先级),因此表达式被解释为(new (Date.toString))()
相同的逻辑也可以应用于…[…]
操作符。
new Foo
具有从右到左的结合性,而对于new Foo()
,“结合性”不适用。我认为在实践中这没有任何区别。有关详细信息,请参见此 SO问题
其中一个更受偏爱吗?
了解了所有这些,可以假设new Foo()
更受欢迎。
new Foo()
而不是new Foo
。到目前为止最好的答案。 - CodeLamanew Object().something()
以及(new Object()).something()
都可以。 - LittleTiger(new Date).toString()
,字符数相同,并且比new Date().toString
更明确。 - Jean Vincent我认为在使用"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 a.b()
和new a().b()
是不同的。在前者中,首先访问a.b
,而在后者中,首先创建一个新的a
。 - Andrew