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

前端 未结 6 2073
清酒与你
清酒与你 2020-11-22 00:41

I have seen objects being created this way:

const obj = new Foo;

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

相关标签:
6条回答
  • 2020-11-22 00:51

    Quoting David Flanagan1:

    As a special case, for the new operator 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 new operator:

    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, JSLint may 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.


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

    0 讨论(0)
  • 2020-11-22 00:51

    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.

    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
    
    0 讨论(0)
  • 2020-11-22 00:54

    There's no difference between the two.

    0 讨论(0)
  • 2020-11-22 01:04

    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"

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

    ╔════════════╦═════════════════════════════╦═══════════════╦═════════════╗
    ║ 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 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.

    2. 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


    Is one preferred over the other?

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

    0 讨论(0)
  • 2020-11-22 01:05

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

    0 讨论(0)
  • 2020-11-22 01:10

    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:

    var someVar = myFunc; // this assigns the function myFunc to someVar
    var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar
    
    0 讨论(0)
提交回复
热议问题