“Yeni” operatörünü kullanarak bir nesne oluştururken parantezleri atlayabilir miyiz?


230

Nesnelerin bu şekilde yaratıldığını gördüm:

const obj = new Foo;

Ama bir nesne oluştururken parantezlerin isteğe bağlı olmadığını düşündüm:

const obj = new Foo();

ECMAScript standardında nesneler oluşturmanın eski yolu geçerli ve tanımlanmış mı? Eski nesne yaratma yöntemi ile sonrakiler arasında herhangi bir fark var mı? Biri diğerine tercih edilir mi?



Güncel referans: ECMAScript 2017 §12.3.3 Yeni Opertator .
RobG

TL; DR: Öncekindennew a.b() farklı olduğuna dikkat edin , ilk new a().b()durumda a.bilk önce erişilirken, ikinci durumda aönce yeni bir tane oluşturulur.
Andrew

Yanıtlar:


239

David Flanagan 1'den alıntı :

Özel bir durum olarak, newyalnızca işleç için JavaScript, işlev çağrısında bağımsız değişken yoksa parantezin atlanmasına izin vererek dilbilgisini basitleştirir. İşte newoperatörü kullanan bazı örnekler :

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

...

Şahsen, kurucu hiçbir argüman almasa bile, her zaman parantez kullanırım.

Ayrıca , parantezi atlarsanız JSLint duygularınıza zarar verebilir. Rapor ediyor Missing '()' invoking a constructorve aracın parantez ihmalini tolere etmesi için bir seçenek yok gibi görünüyor.


1 David Flanagan: JavaScript Kesin Kılavuz: 4. Baskı (sayfa 75)


6
JSLint neden parantez kullanımını teşvik ediyor?
Randomblue

11
Sanırım sadece daha tutarlı sayılıyor.
Daniel Vassallo

12
Birçok JavaScript geliştiricisinin parantez kullandığını görmek ilginç, çünkü "araç (JSLint) onlara bunu söyledi", özellikle developer.mozilla.org/en-US/docs/Web/JavaScript/Guide /… , "<Expletive> dilini icat edenler" new Classparametresiz kurucular için parantez kullanmazlar . Eğer bu 'görüşlü' hecelemiyorsa, ne yaptığını bilmiyorum ...
ack

52
Eh @ack, bu garip olurdu değil dilin mucitler kendi dillerinde belirli özelliklerini vitrin bkz (bu durumda, omit seçeneği yapıcıları üzerinde parantezler) için. Bu özelliği eklemeselerdi, ilk etapta kullanılmaları gerekip gerekmediğini sormazdık. Kullanmamanın pratik bir nedeni şudur: buna new Object.func()eşdeğer DEĞİLDİR new Object().func(). Her zaman parantez içererek bu hatayı yapma olasılığı ortadan kalkar.
nmclean

2
Bir hata yapma olasılığını ortadan kaldırmak istiyorsanız kullanmalısınız (new Object).func(). Ancak , dilinizi öğrenmemek için kötü bir bahane ==vs olduğu gibi ekstra parantez ve ekstra eşit işaretler kullanmayı düşünüyorum ===.
Jean Vincent

79

İkisi arasında farklılıklar vardır:

  • new Date().toString() mükemmel çalışıyor ve geçerli tarihi döndürüyor
  • new Date.toString()" TypeError: Date.toString bir kurucu değil "

Bu olur new Date()ve new Datefarklı önceliğe sahiptir. MDN'ye göre , JavaScript operatör öncelik tablosunun ilgilendiğimiz kısmı aşağıdaki gibidir:

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

Bu tablodan aşağıdakileri takip edin:

  1. new Foo() önceliği daha yüksektir new Foo

    new Foo().operatörle aynı önceliğe sahiptir

    new Foo.operatörden bir seviye daha düşük önceliğe sahiptir

    new Date().toString() mükemmel çalışıyor çünkü (new Date()).toString()

    new Date.toString()" TypeError: Date.toString bir yapıcı değildir " atar çünkü .önceliği new Date(ve "İşlev Çağrısı" ndan daha yüksek önceliğe sahiptir ) ve ifade şu şekilde değerlendirilir:(new (Date.toString))()

    Aynı mantık … [ … ]operatöre uygulanabilir .

  2. new Fooolan sağdan sola birleşim ve için new Foo()"çağrışımsallık" uygulanamaz. Bence pratikte herhangi bir fark yaratmıyor. Ek bilgi için bu SO sorusuna bakın


Biri diğerine tercih edilir mi?

Tüm bunları bilerek new Foo(), tercih edildiği varsayılabilir .


4
Son olarak, soruyu gerçekten cevaplayan ve ince farkı işaret eden biri!
gcampbell

vay, teşekkürler. bana başka bir dili hatırlatıyor en.wikipedia.org/wiki/Brainfuck
John Henckel

İyi açıklanmış, tam olarak neden new Foo()tercih edilmesi gerektiğini açıklıyor new Foo. Şimdiye kadarki en iyi cevap.
CodeLama

Müthiş cevap, öncelik tablosu ve beraberindeki açıklama tamamen netleştiriyor. Bunun yazmayı new Object().something()da nasıl iyi hale getirdiğini açıkladığınıza sevindim (new Object()).something().
LittleTiger

1
Büyük açıklama ama sonuca katılmıyorum ve hala dilinizi biliyorsanız parantez kullanmamanın iyi olduğunu düşünüyorum. BTW bilmiyorsanız JS önceliğini de kullanabilirsiniz (new Date).toString(), aynı karakter sayısı ve daha açık new Date().toString.
Jean Vincent

14

"Yeni" operatörü kullanırken herhangi bir fark olduğunu düşünmüyorum. Bu iki alışkanlık aynı olmadığından, bu alışkanlığa girerken dikkatli olun:

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

1
Noktalı virgülleri atma alışkanlığınız varsa daha da sorunludur. ;-)
RobG

13

Geçirilecek argümanınız yoksa parantezler isteğe bağlıdır. Onları atlamak sadece sözdizimsel şekerdir.


8
Sözdizimsel tuz diyebilirim, ama ymmv.
Thomas Eding

İhtiyaç duyulmadığı takdirde bunları eklemek sözdizimsel şekerdir. :)
Cozzbie

8

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

ES6 spesifikasyonunun iki varyantın nasıl çalıştığını tanımlayan kısmı. Parantezsiz varyant boş bir bağımsız değişken listesi geçirir.

İlginç bir şekilde, iki formun farklı gramer anlamları vardır. Bu, sonucun bir üyesine erişmeye çalıştığınızda ortaya çıkar.

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

ES5 ve ES3'te de iyi tanımlanmış - "Yapıcıda [[Construct]] dahili yöntemini çağırmanın sonucunu döndürerek hiçbir bağımsız değişken (yani, boş bir bağımsız değişken listesi) sağlayın."
Benjamin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.