2010-06-14 7 views
181

widziałem obiekty tworzone w ten sposób:Czy możemy pominąć nawiasy podczas tworzenia obiektu za pomocą operatora "nowego"?

const obj = new Foo; 

Ale myślałem, że nawiasy nie są opcjonalne podczas tworzenia obiektu:

const obj = new Foo(); 

to dawny sposób tworzenia obiektów ważne i określone w standard ECMAScript? Czy są jakieś różnice między poprzednim sposobem tworzenia obiektów a późniejszym? Czy preferujesz jeden nad drugim?

+0

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

+0

Zaktualizowany numer referencyjny: ECMAScript 2017 [* §12.3.3 Nowy operator *] (http: // ecma -international.org/ecma-262/8.0/#sec-new-operator). – RobG

Odpowiedz

192

Cytowanie David Flanagan :

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

... 

Osobiście zawsze używać nawiasów, nawet gdy konstruktor przyjmuje żadnych argumentów.

Ponadto JSLint może zranić uczucia, jeśli pominąć nawias. Zgłasza się Missing '()' invoking a constructor i nie wydaje się, aby narzędzie tolerowało pominięcie nawiasów.


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

+5

Dlaczego JSLint zachęca do używania nawiasów? – Randomblue

+10

Sądzę, że jest to po prostu uważane za bardziej spójne. –

+11

Ciekawe, że wielu programistów JavaScript używa nawiasów po prostu dlatego, że "narzędzie (JSLint) kazało im to zrobić", szczególnie biorąc pod uwagę, że przykłady na https://developer.mozilla.org/en-US/docs/ Web/JavaScript/Guide/Details_of_the_Object_Model, od "facetów, którzy wymyślili język " nie używaj nawiasów na 'nowej klasie' dla konstruktorów bez parametrów. Jeśli to nie znaczy "uparty", nie wiem, co ... – ack

13

Jeśli nie masz argumentów przekazać, nawiasy są opcjonalne. Pominięcie ich jest po prostu cukrem syntaktycznym.

+3

Powiedziałbym, że sól syntaktyczna, ale ymmv. –

5

Nie ma różnicy między tymi dwoma.

14

Nie sądzę, że nie ma żadnej różnicy, gdy używasz operatora "nowego". Bądź ostrożny dostania się tego nawyku, jak tych dwóch linii kodu nie są takie 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

Jeszcze bardziej problematyczne, jeśli masz zwyczaj pomijania średników. ;-) – RobG

5

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

Oto część specyfikacji ES6 który określa w jaki sposób obsługiwać oba warianty. Wariant bez nawiasów przekazuje pustą listę argumentów.

Co ciekawe, obie formy mają różne znaczenia gramatyczne. Pojawia się, gdy próbujesz uzyskać dostęp do członka wyniku.

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

Jest to również dobrze zdefiniowane w ES5 i ES3 - "Zwróć wynik wywołania metody wewnętrznej [[Construct]] na konstruktorze, bez żadnych argumentów (czyli pustej listy argumentów)." –

+0

http://es5.github.io/x11.html#x11.2.2 tutaj jest link do ES5 – guest

41

Istnieją różnice między tymi dwoma:

  • new Date().toString() działa idealnie i zwraca bieżącą datę
  • new Date.toString() rzuca "TypeError: Date.toString nie jest konstruktorem"

Zdarza się, ponieważ new Date() i new Date ha ve różne pierwszeństwo.Według MDN część JavaScript tabeli pierwszeństwa operator jesteśmy zainteresowani wygląda następująco:

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

z tej tabeli wynika, że:

  1. new Foo() ma wyższy priorytet następnie new Foo

    new Foo() ma to samo pierwszeństwo, co . operator

    new Foo ma jeden poziom niższy priorytet następnie . operatora

    new Date().toString() działa perfekcyjnie, ponieważ daje wartość (new Date()).toString()

    new Date.toString() generuje „Błąd typu: data.toString nie konstruktor”, ponieważ ma wyższy priorytet . następnie new Date (i wyższy niż "Wywołanie funkcji") i wyrażenie jest oceniane jako (new (Date.toString))()

    Ta sama logika może być zastosowana do operatora … [ … ].

  2. new Foo ma prawo-lewo asocjatywność i new Foo() "skojarzeń" nie ma zastosowania. Myślę, że w praktyce nie robi to żadnej różnicy. Aby uzyskać dodatkowe informacje, patrz this SO pytanie


Is one preferred over the other?

Wiedząc wszystko, co można przyjąć, że new Foo() jest korzystne.

+1

Wreszcie, ktoś, kto faktycznie odpowiada na pytanie i wskazuje na subtelną różnicę! – gcampbell

+0

Wow, dzięki. przypomina mi inny język https://en.wikipedia.org/wiki/Brainfuck –

+0

Dobrze wyjaśniony, oferuje dokładnie powód, dla którego 'nowy Foo()' powinien być preferowany zamiast 'nowego Foo'. Najlepsza jak dotąd odpowiedź. – CodeLama

Powiązane problemy