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

前端 未结 6 2203
清酒与你
清酒与你 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 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.

提交回复
热议问题