javascript - Kan vi utelate parenteser når vi oppretter et objekt ved å bruke «new»-operatoren?


Jeg har sett objekter bli laget på denne måten:

const obj = new Foo;

Men jeg trodde at parentesene ikke er valgfrie når man oppretter et objekt:

const obj = new Foo();

Er den tidligere måten å lage objekter på gyldig og definert i ECMAScript-standarden? Er det noen forskjeller mellom den tidligere måten å lage objekter på og den senere? Er den ene å foretrekke fremfor den andre?

Svar #1

Siterer David Flanagan1:

Som et spesielt tilfelle, for new-operatoren bare, forenkler JavaScript grammatiken ved å tillate at parentesene utelates dersom det ikke er noen argumenter i funksjonskallet. Her er noen eksempler som bruker new-operatoren:

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

...

Personlig bruker jeg alltid parentesene, selv når konstruktøren ikke tar noen argumenter.

I tillegg kan JSLint såre følelsene dine hvis du utelater parentesene. Det rapporterer Missing '()' invoking a constructor, og det ser ikke ut til å være et alternativ for verktøyet å tolerere utelatelse av parenteser.


1 David Flanagan: JavaScript den definitive guiden: 4. utgave (side 75)

Svar #2

Det er forskjeller mellom de to:

  • new Date().toString() fungerer perfekt og returnerer den nåværende datoen
  • new Date.toString() kaster "TypeError: Date.toString er ikke en konstruktør"

Det skjer fordi new Date() og new Date har forskjellig prioritet. Ifølge MDN ser delen av JavaScript-operatørprioritetstabellen vi er interessert i slik ut:

PrioritetOperatørtypeAssociativitetOperatører
18Medlems tilgang
Beregnet medlems tilgang
new (med argumentliste)
venstre-til-høyre
venstre-til-høyre
ikke aktuelt
… . …
… [ … ]
ny … ( … )
17Funksjonskall
new (uten argumentliste)
venstre-til-høyre
høyre-til-venstre
… ( … )
ny …

Fra denne tabellen følger det at:

  1. new Foo() har høyere presedens enn new Foo

    new Foo() har samme presedens som .-operatoren

    new Foo har ett nivå lavere presedens enn .-operatoren

    new Date().toString() fungerer perfekt fordi det evalueres som (new Date()).toString()

    new Date.toString() kaster "TypeError: Date.toString er ikke en konstruktør" fordi . har høyere presedens enn new Date (og høyere enn "Funksjonskall") og uttrykket evalueres som (new (Date.toString))()

    Den samme logikken kan brukes på … [ … ]-operatoren.

  2. new Foo har høyre-til-venstre assosiativitet, og for new Foo() er «assosiativitet» ikke relevant. Jeg tror i praksis gjør det ingen forskjell. For mer informasjon, se dette SO-spørsmålet


Er den ene foretrukket fremfor den andre?

Med all den kunnskapen kan det antas at new Foo() foretrekkes.

Svar #3

Jeg tror ikke det er noen forskjell når du bruker «new»-operatoren. Vær forsiktig med å få denne vanen, da disse to kodelinjene IKKE er det samme:

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

Svar #4

Hvis du ikke har argumenter å sende, er parentesene valgfrie. Å utelate dem er bare syntaktisk sukker.

Relaterte artikler