2010-06-14 5 views
181

J'ai vu des objets créés de cette façon:Peut-on omettre des parenthèses lors de la création d'un objet en utilisant le "nouvel" opérateur?

const obj = new Foo; 

Mais je pensais que les parenthèses ne sont pas en option lors de la création d'un objet:

const obj = new Foo(); 

est l'ancienne façon de créer des objets valides et définis dans la norme ECMAScript? Y a-t-il des différences entre l'ancienne façon de créer des objets et la dernière? Est-ce que l'un est préféré à l'autre?

+0

http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.2 – SheetJS

+0

Référence mise à jour: ECMAScript 2017 [* §12.3.3 Le nouvel Opérateur *] (http: // ecma -international.org/ecma-262/8.0/#sec-new-operator). – RobG

Répondre

192

David Flanagan1 Citant:

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(); 

... 

Personnellement, j'utilise toujours la parenthèse, même si le constructeur ne prend aucun argument.

En outre, JSLint peut blesser vos sentiments si vous omettez la parenthèse. Il signale Missing '()' invoking a constructor, et il ne semble pas y avoir d'option permettant à l'outil de tolérer l'omission de parenthèses.


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

+5

Pourquoi JSLint encourage-t-il l'utilisation de parenthèses? – Randomblue

+10

Je suppose que c'est juste considéré comme plus cohérent. –

+11

Je trouve intéressant de voir que de nombreux développeurs JavaScript utilisent des parenthèses simplement parce que "l'outil (JSLint) leur a dit de le faire", d'autant plus que les exemples sur https://developer.mozilla.org/en-US/docs/ Web/JavaScript/Guide/Details_of_the_Object_Model, à partir de "les gars qui ont inventé le langage " n'utilisez aucune parenthèse sur 'new Class' pour les constructeurs sans paramètre. Si cela ne veut pas dire 'opiniâtre', je ne sais pas ce que ... – ack

13

Si vous ne disposez pas d'arguments pour passer, les parenthèses sont facultatifs. Les omettre est juste du sucre syntaxique.

+3

Je dirais que le sel syntactique, mais ymmv. –

5

Il n'y a pas de différence entre les deux.

14

Je ne pense pas qu'il y ait une différence lorsque vous utilisez le "nouveau" opérateur. Faites attention à entrer dans cette habitude, comme ces deux lignes de code ne sont pas identiques:

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

Encore plus problématique si vous avez l'habitude d'omettre les points-virgules. ;-) – RobG

5

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

est ici la partie de la spécification ES6 qui définit comment les deux variantes fonctionnent. La variante sans parenthèses transmet une liste d'arguments vide.

Fait intéressant, les deux formes ont des significations grammaticales différentes. Cela arrive lorsque vous essayez d'accéder à un membre du résultat.

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

Il est également bien défini dans ES5 et ES3 - "Renvoie le résultat de l'appel de la méthode interne [[Construct]] sur le constructeur, en ne fournissant aucun argument (c'est-à-dire une liste vide d'arguments)." –

+0

http://es5.github.io/x11.html#x11.2.2 voici le lien pour ES5 – guest

41

Il existe des différences entre les deux:

  • new Date().toString() fonctionne parfaitement et renvoie la date actuelle
  • new Date.toString() lance "TypeError: Date.toString est pas un constructeur"

Il arrive parce que new Date() et new Date ha une préséance différente.Selon MDN la partie du tableau de priorité des opérateurs JavaScript qui nous intéresse ressemble à:

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

À partir de ce tableau suit que:

  1. new Foo() a une priorité plus élevée alors new Foo

    new Foo() a la même précédence que . opérateur

    new Foo a une priorité niveau inférieur alors . opérateur

    new Date().toString() fonctionne parfaitement, car il évalue comme (new Date()).toString()

    new Date.toString() lancers francs « TypeError: Date.toString est pas un constructeur » parce . a une priorité plus élevée alors new Date (et supérieur à "Appel de fonction") et l'expression est évaluée comme (new (Date.toString))()

    La même logique peut être appliquée à l'opérateur … [ … ].

  2. new Foo a droit à gauche associativité et new Foo() « associativité » est pas applicable. Je pense qu'en pratique cela ne fait aucune différence. Pour plus d'informations voir this question si


Is one preferred over the other?

Sachant tout ce que l'on peut supposer que new Foo() est préféré.

+1

Enfin, quelqu'un qui répond réellement à la question et souligne la différence subtile! – gcampbell

+0

wow, merci. me rappelle une autre langue https://en.wikipedia.org/wiki/Brainfuck –

+0

Bien expliqué, offre exactement la raison pour laquelle 'new Foo()' devrait être préféré à 'new Foo'. La meilleure réponse jusqu'à présent. – CodeLama

Questions connexes