`New Object ()` ve object literal gösterimi arasındaki fark nedir?


200

Nesne oluşturmak için bu yapıcı tabanlı sözdizimi arasındaki fark nedir:

person = new Object()

... ve bu gerçek sözdizimi:

person = {
    property1 : "Hello"
};

Her ikisi de aynı şeyi yapıyor gibi görünüyor, ancak JSLint nesne değişmez gösterim kullanmayı tercih ediyor.

Hangisi daha iyi ve neden?


7
Hepsi aynı: a = new Object, a = new Object(), a = {}, edebi, çok basit olmasına önce daha hızlı, daha yeni derleyiciler ifadem yanlış olduğu yol açmış olabileceği olduğunu söylerken bazı testler Ben koştum. Aynısı diziler için de geçerlidir
Juan Mendes

8
Umarız varglobal ad alanını kirletmemek ve değişkenleriniz için yığındaki geçerli kaydın ötesine bakma gereği yaratmamak için değişkenlerinizi uygulama kodunuzdaki anahtar kelimeyle bildirirsiniz .
Samo

1
Temel olarak, bir programın yürütülmesi sırasında herhangi bir noktada, bir kayıt veya blok yığını vardır. Her kaydın bu kapsamda oluşturulan değişkenlerin bir listesi vardır. JavaScript'te, bir ifade bir değişken içeriyorsa ve yorumlayıcı bu kapsamın yığın kaydında bulamazsa, değişkeni bulana kadar bir sonraki kayda kadar devam eder. Daha fazla bilgi davidshariff.com/blog/…
Samo

2
JSLint'lerden kaçınmak, iyi bir geliştirici olmanın ilk adımıdır. Kullanmak newvasat bir dilin anlamsız nitpike aşan bir sözleşmedir. Kullanım newonun anlamı açıktır çünkü. Davanın% 99,9'unda performans kazançları önemsizdir.
Hal50000

1
@ Hal50000 vasat dil kime göre?
Xam

Yanıtlar:


125

İkisi de aynı şeyi yapar (biri alışılmadık bir şey yapmadığı sürece), ikincinizin bir nesne oluşturması ve ona bir özellik eklemesinin dışında. Ancak gerçek gösterim, kaynak kodunda daha az yer kaplar. Neler olduğuna dair açıkça tanınabilir, bu yüzden kullanarak new Object(), sadece daha fazla yazıyorsunuz ve (teorik olarak, JavaScript motoru tarafından optimize edilmezse) gereksiz bir işlev çağrısı yapıyoruz.

Bunlar

person = new Object() /*You should put a semicolon here too.  
It's not required, but it is good practice.*/ 
-or-

person = {
    property1 : "Hello"
};

teknik olarak aynı şeyi yapmayın. İlki sadece bir nesne yaratır. İkincisi bir tane oluşturur ve bir özellik atar. İlkinin aynı olması için özelliği oluşturmak ve atamak için ikinci bir adıma ihtiyacınız vardır.

Birisinin yapabileceği "olağandışı bir şey", varsayılan Objectglobal gölgelendirmek veya atamak olacaktır :

// Don't do this
Object = 23;

Bu son derece olağandışı durumda, new Objectbaşarısız {}olacak ama işe yarayacak.

Uygulamada, kullanmak new Objectyerine asla bir sebep yoktur {}(çok sıradışı bir şey yapmadıysanız).


11
Yazar bu cevabı doğru olarak seçti, ancak eksik. Bellek ayırmaya başladığınızda iki sözdizimi arasında farklar olduğunu unutmayın.
newshorts

2
Hiçbir fark yok. Aşağıdaki yanıtlardan birine atıfta bulunuyorsanız, prototip tabanlı nesne modeli ve kalıtımdan bahsedildiği için konu dışıdır (oradaki kod, düz Nesneden miras alan bir Obj sınıfı kurar). Bu soru, bazı özel sınıfın bir örneğini oluşturmakla ilgili değildir - Object nesnesinin bir örneğini oluşturmakla ilgilidir ve bu sorunun doğru cevabı "hiçbir fark yoktur".
dos

FYI da () new Object()gerekli değildir. (
Royi Namir

Mevcut şartnameden itibaren yeni kullanmaya ihtiyacımız olmadığını düşünüyorum . Düşüncelerinizi bana bildirin @kevin
Pavan Mahesh

1
Ayrıca, miras zincirinden miras almayan bir nesne istiyorsanız Object create and pass null değerini de kullanabilirsiniz. Eşit değildirler ve sırasıyla yararlı amaçlara sahiptirler.
Aaron

235

Örneğinizde olduğu gibi yöntem içermeyen basit bir nesne için fark yoktur. Ancak, nesnenize yöntem eklemeye başladığınızda büyük bir fark vardır.

Gerçek yol:

function Obj( prop ) { 
    return { 
        p : prop, 
        sayHello : function(){ alert(this.p); }, 
    }; 
} 

Prototip yolu:

function Obj( prop ) { 
    this.p = prop; 
} 
Obj.prototype.sayHello = function(){alert(this.p);}; 

Her iki yol Objda bunun gibi örneklerin oluşturulmasına izin verir :

var foo = new Obj( "hello" ); 

Ancak, tam anlamıyla sayHello, nesnenin her örneği içinde yöntemin bir kopyasını taşırsınız . Oysa prototip yolu ile yöntem, nesne prototipinde tanımlanır ve tüm nesne örnekleri arasında paylaşılır. Çok fazla nesneniz veya çok sayıda yönteminiz varsa, gerçek yol oldukça büyük bellek israfına yol açabilir.


39
Bana göre soru daha çok, boş nesneler oluşturmak için new Object()vs {}ile kullanım arasındaki farklar hakkındaydı .
Peter

11
@Lobabob İlk cümlenin yanı sıra, bu cevap aslında OP'nin sorusu hakkında herhangi bir bilgi sağlamaz. Hiçbir yerde 'yeni Object () `içermiyor. Açıkçası Bay David'in soruyu yanlış anladığını düşünüyorum.
JLRishe

17
Bunu gönderdiğimde kabul edilen cevap zaten oradaydı ve kabul etti. Ve OP sorusunu mükemmel bir şekilde cevaplıyor, bu yüzden aynı şeyi tekrarlamayacaktım. Cevabımı ağırlıklı olarak konuyu boş / basit nesnelerin ötesine genişletmek için yayınladım. Bu durumda orada olduğunu bahsetmemiz olan önemli bir fark.
Rémy DAVID

3
Bu cevap konu dışı. Kodunuzda, Obj, Object'ten devralınan ayrı bir sınıftır. Nesne değişmez gösterimini kullandığınızda, Obj yerine Object sınıfını kullanırsınız. Elbette, prototipinde yöntemle bir sınıf oluşturmak, bellek ayak izini çok sayıda düz Nesne oluşturmaktan ve özellikleri olarak yöntem eklemekten daha küçük hale getirecektir, ancak bu burada sorulan soru ile tamamen ilgisizdir. Bu sorunun doğru cevabı "hayır, kesinlikle hiçbir fark yoktur (belki okunabilirlik dışında)" dır.
dos

3
Bu cevap için, benimki gibi bir soruya dayanarak geldim, ancak tam olarak bilmem gerekenleri öğrendim. Teşekkür ederim.
Pat Migliaccio

55

JavaScript'te, yeni bir boş nesneyi iki şekilde bildirebiliriz:

var obj1 = new Object();  
var obj2 = {};  

Bu ikisinin perde arkasında nasıl çalıştıklarına dair önemli bir fark olduğunu öne sürecek hiçbir şey bulamadım (yanlışsam lütfen beni düzeltin - bilmek isterim). Bununla birlikte, ikinci yöntem (nesne değişmez gösterimini kullanarak) birkaç avantaj sağlar.

  1. Daha kısadır (kesin olmak için 10 karakter)
  2. Anında nesneler oluşturmak daha kolay ve daha yapılandırılmıştır
  3. Bazı soytarı nesnenin yanlışlıkla geçersiz kılınmış olması önemli değil

Name ve TelNo üyelerini içeren yeni bir nesne düşünün. Yeni Object () kuralını kullanarak bunu şu şekilde oluşturabiliriz:

var obj1 = new Object();  
obj1.Name = "A Person";  
obj1.TelNo = "12345"; 

Expando Özellikleri JavaScript özelliği bize yeni üyelere anında bu şekilde oluşturmak için ve biz niyetinde ne başarmak sağlar. Ancak, bu şekilde çok yapılandırılmış veya kapsüllenmiş değildir. Üyeleri, oluşturma sırasında genişletme özelliklerine ve atama sonrası atamaya güvenmek zorunda kalmadan belirtmek istersek ne olur?

Nesne hazır gösterimi yardımcı olabilir:

var obj1 = {Name:"A Person",TelNo="12345"};  

Burada aynı etkiyi bir kod satırında ve önemli ölçüde daha az karakterde elde ettik.

Yukarıdaki nesne oluşturma yöntemlerine ilişkin daha fazla tartışmayı şu adreste bulabilirsiniz: JavaScript ve Nesneye Yönelik Programlama (OOP).

Ve son olarak, Object'i aşan salak ne olacak? Bunun mümkün olmadığını düşündünüz mü? Eh, bu JSFiddle aksi kanıtlıyor. Nesne hazır gösterimini kullanmak, bu soytarıya faul düşmemizi önler.

( Http://www.jameswiseman.com/blog/2011/01/19/jslint-messages-use-the-object-literal-notation/ adresinden )


1
Object.Create hakkında ne dersiniz? Bakınız: developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Phil

Bir new Object()şeyin Nesne işlevinin üzerine yazılması olasılığı nedeniyle nesne değişmezlerini tercih edecekseniz, Object.keystanımsız olmadığından emin olmak için yardımcıları kullandığınızda , saçmalıklara inenlerden emin olmalısınız. İnsanlara her zaman gerçek gösterimi kullanmalarını öneririm, ancak bence bu tür bir argüman, bu şekilde düşünmenin sonuçlarını düşündüğünüzde parçalanıyor.
philraj

41

Node.js kullanan makinemde aşağıdakileri çalıştırdım:

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');

Not, bu burada bulunanın bir uzantısıdır: Neden arr = [] arr = new Array'dan daha hızlı?

benim çıktı aşağıdaki oldu:

Testing Array:
using[]: 1091ms
using new: 2286ms
Testing Object:
using{}: 870ms
using new: 5637ms

bu nedenle açıkça {} ve [], boş nesneler / diziler oluşturmak için yenisini kullanmaktan daha hızlıdır.


3
Bu sorunun gerçekten aradığı cevap olduğunu hissediyorum, ancak bunu sağlamak için birkaç özellikli bir nesne üzerinde ayrıca test edildiğini görmek isterdim.
Chase Sandmann

2
İlginç numaralar. Bunun farkında olması gereken insanlar var, ama 200.000 nesnenin bile ayrılmasının bana sadece 5.6ms'ye mal olacağını, bu yüzden endişelenmeyeceğim.

Düğümde 10.13.0 şeyler DEĞİŞTİRİLDİ Test Dizisi: [] kullanarak: 117.178ms yeni kullanarak: 116.947ms Test Nesnesi: kullanarak {}: 116.252ms kullanarak yeni: 115.910ms
PirateApp

31

Buradaki herkes ikisinin benzerlikleri hakkında konuşuyor. Farklılıkları göstereceğim.

  1. Kullanarak new Object()başka bir nesne geçirebilirsiniz. Bariz sonuç, yeni oluşturulan nesnenin aynı referansa ayarlanmasıdır. İşte bir örnek kod:

    var obj1 = new Object();
    obj1.a = 1;
    var obj2 = new Object(obj1);
    obj2.a // 1
  2. Kullanım, OOP nesnelerinde olduğu gibi nesnelerle sınırlı değildir. Diğer türler de ona geçirilebilir. Fonksiyon türü buna göre ayarlayacaktır. Örneğin, ona 1 tamsayısını iletirsek, bizim için bir tür numarası nesnesi oluşturulur.

    var obj = new Object(1);
    typeof obj // "number"
  3. Yukarıdaki method ( new Object(1)) kullanılarak oluşturulan nesne, bir özellik eklenirse nesne türüne dönüştürülür.

    var obj = new Object(1);
    typeof obj // "number"
    obj.a = 2;
    typeof obj // "object"
  4. Nesne, alt nesne nesnesinin bir kopyasıysa, türü dönüştürme olmadan özelliği ekleyebiliriz.

    var obj = new Object("foo");
    typeof obj // "object"
    obj === "foo" // true
    obj.a = 1;
    obj === "foo" // true
    obj.a // 1
    var str = "foo";
    str.a = 1;
    str.a // undefined

3
Son iki satır hakkında çok kafam karıştı .. Neden str.a'ya 1 değerini atarsanız, str.a tanımsızdır? .. @Jermin Bazazin
Andrea Scarafoni

3
@AndreaScarafoni str, tür olduğundan , stringbir özellik atayamazsınız. jsfiddle.net/grq6hdx7/1
Chris Bier

1
4'ün yanıtı değişti mi? Yanlış, doğru değil, en son Chrome 53'te var obj = new Object("foo"); typeof obj; obj === "foo" // true
William Hilton

21

Aslında, JavaScript'te nesne oluşturmanın birkaç yolu vardır. Sadece bir nesne oluşturmak istediğinizde, " new " operatörünü kullanarak " yapıcı tabanlı " nesneler yaratmanın faydası yoktur . Bu, " nesne değişmezi " sözdizimini kullanarak bir nesne oluşturmakla aynıdır . Ancak , " prototypal miras " ı düşündüğünüzde " new " operatörü ile oluşturulan " yapıcı tabanlı " nesneler inanılmaz bir şekilde kullanılabilir . Değişmez sözdizimi ile oluşturulan nesnelerle miras zincirini koruyamazsınız. Ancak bir yapıcı işlevi oluşturabilir , prototipine özellikler ve yöntemler ekleyebilirsiniz."işleci, bu yapıcı işlevinin prototipiyle birlikte eklenen tüm yöntemlere ve özelliklere erişebilecek bir nesne döndürür.

Oluşturucu işlevini kullanarak bir nesne oluşturma örneği aşağıdadır (alttaki kod açıklamasına bakın):

function Person(firstname, lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
}

Person.prototype.fullname = function() {
    console.log(this.firstname + ' ' + this.lastname);
}

var zubaer = new Person('Zubaer', 'Ahammed');
var john = new Person('John', 'Doe');

zubaer.fullname();
john.fullname();

Artık Kişi oluşturma işlevini örnekleyerek istediğiniz kadar nesne oluşturabilirsiniz ve hepsi de ondan fullname () devralır.

Not: " this " anahtar sözcüğü, yapıcı işlevi içindeki boş bir nesneye işaret eder ve " new " operatörünü kullanarak Person'ten yeni bir nesne oluşturduğunuzda, " this " anahtar sözcüğüyle eklenen tüm özellikleri ve yöntemleri içeren bir nesneyi otomatik olarak döndürür . Ve bu nesne , Kişi yapıcı fonksiyonunun prototipiyle (bu yaklaşımın ana avantajıdır) ekli yöntemleri ve özellikleri kesin olarak devralacaktır .

Bu arada, " nesne değişmezi " sözdizimiyle aynı işlevselliği elde etmek istiyorsanız, aşağıdaki gibi tüm nesnelerde tam ad () oluşturmanız gerekir:

var zubaer = {
    firstname: 'Zubaer',
    lastname: 'Ahammed',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

var john= {
    firstname: 'John',
    lastname: 'Doe',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

zubaer.fullname();
john.fullname();

Sonunda, neden nesne değişmez yaklaşımı yerine yapıcı işlev yaklaşımını kullanmam gerektiğini sorarsanız :

*** Prototippal kalıtım, son derece yararlı ve güçlü olabilen basit bir kalıtım zincirine izin verir.

*** Yapıcı işlev prototipinde tanımlanan ortak yöntemleri ve özellikleri devralarak bellek tasarrufu sağlar. Aksi takdirde, bunları tüm nesnelerde tekrar tekrar kopyalamanız gerekir.

Umarım bu mantıklı gelir.


Teşekkürler! Karl eksik "bu" nesnesini kelimenin tam anlamıyla eklemek için. Bu korkunç bir hataydı ... Bu tür bir hata yapmamalıydım.
Md. Zubaer Ahammed

"Değişmez sözdizimi ile oluşturulan bir nesneden devralınamazsınız." - Doğru değil (inanıyorum). Gerektiği gibi kalıtım zincirlerini kullanabilir Object.create(<object defined using literal notation>)veya new Object(<object defined using literal notation>)oluşturabilirsiniz.
balajeerc

@balajeerc Yorumunuz için teşekkürler. Aslında "Değişmez sözdizimi ile oluşturulan nesnelerle miras zincirini koruyamazsınız" olmalıdır. Cevap birden çok adımda: 1. Object.create (): Evet, bir nesneyi değişmez olarak geçirmek mümkündür ve nesne değişmezinden geçen prototipin yeni bir nesnesini döndürür. Ancak yapıcı işlevinin ne olduğunu bilmiyor ya da yaratıldığı nesneyi hatırlamıyor. Böylece, testobj1.constructor boş bir işlev döndürür ve üst / ata olarak bu nesne değişmezine özellikler / yöntemler eklemenin bir yolu olmayacaktır.
Md. Zubaer Ahammed

@balajeerc 2. new Object (): Bu durumda neredeyse aynı şey olur. Üstelik hafızayı düşünmek daha da kötü. Özellikleri ve yöntemleri prototipine koymak yerine, yalnızca iletilen nesne değişmezinden her şeyi kopyalar ve döndürülen nesneye koyar. Hafıza için iyi değil. Diğer taraftan, anında yöntem ve özellikleri düzenleyebileceğiniz bir yapıcı işleviyle gerçek miras zincirine odaklandım ve yapıcı yöntemini kullanarak oluşturulan diğer nesneler de yalnızca bu yapıcı işlevine işaret ettikleri için etkilenir (kopyalamak yerine) .
Md. Zubaer Ahammed

@balajeerc Örnek:function Person(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; } Person.prototype.fullname = function() { console.log(this.firstname + ' ' + this.lastname); } var zubaer = new Person('Zubaer', 'Ahammed'); var john = new Person('John', 'Doe'); zubaer.fullname(); // Zubaer Ahammed john.fullname(); // John Doe zubaer.constructor.prototype.fullname = function() { console.log( 'Hello ' + this.firstname); } zubaer.fullname(); // Hello Zubaer john.fullname(); // Hoello John
Md. Zubaer Ahammed

9

Ayrıca, O'Really javascript kitaplarının bazılarına göre .... (alıntılanmıştır)

Değişmezleri Nesne yapıcısının aksine kullanmanın bir başka nedeni de kapsam çözümlemesi olmamasıdır. Aynı ada sahip yerel bir kurucu oluşturmuş olmanız mümkün olduğundan, yorumlayıcının, kapsam nesnesini global Object kurucusunu bulana kadar Object () adını verdiğiniz yerden sonuna kadar araması gerekir.


24
Bekle O'Really bir yazım hatası mı yoksa kasıtlı bir cinayet miydi? Kitaplarını pazarlamak için kullanıyor olmalılar!
Tim Ogilvy

3

ES6 / ES2015 için bir fark buldum. Nesneyi çevrelemediğiniz sürece, stenografi ok işlevi sözdizimini kullanarak nesneyi döndüremezsiniz new Object().

> [1, 2, 3].map(v => {n: v});
[ undefined, undefined, undefined ]
> [1, 2, 3].map(v => new Object({n: v}));
[ { n: 1 }, { n: 2 }, { n: 3 } ]

Bunun nedeni, derleyicinin {}parantezler tarafından karıştırılması ve n: ibir etiket olduğunu düşünmesidir : ifade yapısı; noktalı virgül isteğe bağlıdır, bu yüzden şikayet etmez.

Nesneye başka bir özellik eklerseniz, sonuçta bir hata verir.

$ node -e "[1, 2, 3].map(v => {n: v, m: v+1});"
[1, 2, 3].map(v => {n: v, m: v+1});
                           ^

SyntaxError: Unexpected token :

4
Yine de bir ok işlevi kullanabilirsiniz, sadece daha fazla diş teline ve dönüşe ihtiyacınız var: [1, 2, 3].map(v => { return {n: v}; });aynı şeyi netleştireceksiniz ...
Heretic Monkey

Elbette normal ok işlevlerini kullanabilirsiniz, bahsettiğim şey steno versiyonuydu, yani ve bu durumda ve arasındaki param => return_valuefark . {}new Object()
Andrei Simionescu

11
Yine de stenografi sürümünü VE normal ok işlevlerini kullanabilirsiniz. Sadece {n: v} bir çift parantez ile sarın:[1, 2, 3].map(v => ({n: v}));
Stephen C

1

2019 Güncellemesi

OSX High Sierra 10.13.6 düğüm sürüm 10.13.0'da @rjloura ile aynı kodu çalıştırdım ve bunlar sonuçlar

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');


Testing Array:
using[]: 117.613ms
using new: 117.168ms
Testing Object:
using{}: 117.205ms
using new: 118.644ms

-2

10 bin örnek oluşturursanız bellek kullanımı farklıdır. new Object()sadece bir kopyasını tutarken {}10 bin kopyasını tutar.


7
newyeni bir nesne oluşturur. Her ikisi de aynı miktarda bellek kullanır.
Artyer
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.