que propiedades new herencia clases javascript new-operator

javascript - propiedades - ¿Podemos omitir paréntesis al crear un objeto utilizando el operador "nuevo"?



prototype javascript que es (6)

He visto objetos creados de esta manera:

const obj = new Foo;

Pero pensé que los paréntesis no son opcionales al crear un objeto:

const obj = new Foo();

¿La forma anterior de crear objetos es válida y está definida en el estándar ECMAScript? ¿Hay diferencias entre la forma anterior de crear objetos y la posterior? ¿Se prefiere una sobre la otra?


Citando a David Flanagan 1 :

Como caso especial, solo para el new operador, JavaScript simplifica la gramática al permitir que se omita el paréntesis si no hay argumentos en la llamada a la función. Aquí hay algunos ejemplos usando el new operador:

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

Personalmente, siempre uso el paréntesis, incluso cuando el constructor no toma argumentos.

Además, JSLint puede herir sus sentimientos si omite el paréntesis. Informa que Missing ''()'' invoking a constructor , y no parece haber una opción para que la herramienta tolere la omisión de paréntesis.

1 David Flanagan: JavaScript the Definitive Guide: 4th Edition (página 75)


Hay diferencias entre los dos:

  • new Date().toString() funciona perfectamente y devuelve la fecha actual
  • new Date.toString() lanza " TypeError: Date.toString no es un constructor "

Ocurre porque la new Date() y la new Date tienen prioridad diferente. De acuerdo con MDN la parte de la tabla de precedencia del operador de JavaScript en la que estamos interesados ​​se ve así:

╔════════════╦═════════════════════════════╦═══════════════╦═════════════╗ ║ 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 … ║ ╚════════════╩═════════════════════════════╩═══════════════╩═════════════╝

De esta tabla se desprende que:

  1. new Foo() tiene mayor prioridad que el new Foo

    new Foo() tiene la misma precedencia que . operador

    new Foo tiene un nivel de prioridad más bajo que el . operador

    new Date().toString() funciona perfectamente porque se evalúa como (new Date()).toString()

    new Date.toString() lanza " TypeError: Date.toString no es un constructor " porque . tiene mayor prioridad que la new Date (y más alto que "Llamada de función") y la expresión se evalúa como (new (Date.toString))()

    La misma lógica se puede aplicar al operador … [ … ] .

  2. new Foo tiene asociatividad de derecha a izquierda y para el new Foo() "asociatividad" no es aplicable. Creo que en la práctica no hace ninguna diferencia. Para información adicional vea this pregunta de SO

¿Se prefiere una sobre la otra?

Sabiendo todo eso, se puede suponer que se prefiere new Foo() .


No creo que haya ninguna diferencia cuando se utiliza el operador "nuevo". Tenga cuidado al entrar en este hábito, ya que estas dos líneas de código NO son lo mismo:

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


No hay diferencia entre los dos.


Si no tiene argumentos para pasar, los paréntesis son opcionales. Omitirlos es solo azúcar sintáctica.


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

Aquí está la parte de la especificación ES6 que define cómo operan las dos variantes. La variante sin paréntesis pasa una lista de argumentos vacía.

Curiosamente, las dos formas tienen diferentes significados gramaticales. Esto aparece cuando intenta acceder a un miembro del resultado.

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