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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3034941/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:01:21  来源:igfitidea点击:

Can we omit parentheses when creating an object using the "new" operator?

javascriptnew-operator

提问by Behrang Saeedzadeh

I have seen objects being created this way:

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

const obj = new Foo;

But I thought that the parentheses are not optional when creating an object:

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

const obj = new Foo();

Is the former way of creating objects valid and defined in the ECMAScript standard? Are there any differences between the former way of creating objects and the later? Is one preferred over the other?

前一种创建对象的方式是否有效并在 ECMAScript 标准中定义?前者和后者创建对象的方式有什么区别吗?一个比另一个更受欢迎吗?

回答by Daniel Vassallo

Quoting David Flanagan1:

引用大卫弗拉纳根1

As a special case, for the newoperator only, JavaScript simplifies the grammar by allowing the parenthesis to be omitted if there are no arguments in the function call. Here are some examples using the newoperator:

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

...

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

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

...

Personally, I always use the parenthesis, even when the constructor takes no arguments.

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

In addition, JSLintmay hurt your feelings if you omit the parenthesis. It reports Missing '()' invoking a constructor, and there doesn't seem to be an option for the tool to tolerate parenthesis omission.

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



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

1David Flanagan:JavaScript 权威指南:第 4 版(第 75 页)

回答by traxium

There are differences between the two:

两者有以下区别:

  • new Date().toString()works perfectly and returns the current date
  • new Date.toString()throws "TypeError: Date.toString is not a constructor"
  • new Date().toString()完美运行并返回当前日期
  • new Date.toString()抛出“类型错误:Date.toString 不是构造函数

It happens because new Date()and new Datehave different precedence. According to MDNthe part of JavaScript operator precedence table we are interested in looks like:

它发生是因为new Date()new Date具有不同的优先级。根据MDN,我们感兴趣的 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 …       ║
╚════════════╩═════════════════════════════╩═══════════════╩═════════════╝

From this table follows that:

从这张表可以看出:

  1. new Foo()has higher precedence than new Foo

    new Foo()has the same precedence as .operator

    new Foohas 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.

  2. new Foohas right-to-leftassociativity and for new Foo()"associativity" isn't applicable. I think in practice it doesn't make any difference. For additional information see thisSO question

  1. 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))()

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

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



Is one preferred over the other?

一个比另一个更受欢迎吗?

Knowing all that, it can be assumed that new Foo()is preferred.

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

回答by jbabey

I don't think there is any difference when you are using the "new" operator. Be careful about getting into this habit, as these two lines of code are NOT the same:

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

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

回答by Josh

If you do not have arguments to pass, the parentheses are optional. Omitting them is just syntactic sugar.

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

回答by guest

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-new-operator-runtime-semantics-evaluation

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-new-operator-runtime-semantics-evaluation

Here's the part of the ES6 spec that defines how the two variants operate. The no-parentheses variant passes an empty argument list.

这是 ES6 规范中定义这两种变体如何运行的部分。无括号变体传递一个空参数列表。

Interestingly, the two forms have different grammatical meanings. This comes up when you try to access a member of the result.

有趣的是,这两种形式具有不同的语法含义。当您尝试访问结果的成员时会出现这种情况。

new Array.length // fails because Array.length is the number 1, not a constructor
new Array().length // 0

回答by Ivan

There's no difference between the two.

两者没有区别。