JavaScript'in "yeni" anahtar kelimesi zararlı mıdır? [kapalı]


568

Başka bir soruda , kullanıcı newanahtar kelimenin kullanımının tehlikeli olduğunu belirtti ve kullanmayan nesne oluşturma için bir çözüm önerdi new. Bunun doğru olduğuna inanmadım, çünkü Prototip, Scriptaculous ve diğer mükemmel JavaScript kütüphanelerini kullandım ve herkes newanahtar kelimeyi kullandı .

Buna rağmen dün Douglas Crockford'un YUI tiyatrosundaki konuşmasını izliyordum ve aynı şeyi söyledi, newartık kodunda artık anahtar kelimeyi kullanmadı ( JavaScript üzerinde Crockford - III. Hareket: Ultimate - 50:23) dakika ).

newAnahtar kelimeyi kullanmak 'kötü' mü? Kullanmanın avantajları ve dezavantajları nelerdir?


90
Yeni anahtar kelimeyi kullanmak 'kötü' DEĞİLDİR. Ancak unutursanız, nesne yapıcısını normal bir işlev olarak adlandırırsınız. Eğer kurucunuz yürütme bağlamını kontrol etmezse, 'this' ifadesinin yeni örnek yerine farklı bir nesneyi (genellikle global nesneyi) gösterdiğini fark etmez. Bu nedenle kurucunuz global nesneye (pencere) özellikler ve yöntemler ekleyecektir. 'This' öğesinin nesne işlevindeki nesnenizin bir örneği olup olmadığını her zaman kontrol ederseniz, bu sorunla karşılaşmazsınız.
Kristian B

5
Bunu anlamıyorum. Bir yandan doug kullanımı caydırır new. Ama YUI kütüphanesine baktığınızda. Her newyerde kullanmak zorundasın . Gibi var myDataSource = new Y.DataSource.IO({source:"./myScript.php"}); .
aditya_gaur

2
@aditya_gaur Bunun nedeni, bir nesnenin başlatılmasına ihtiyacınız initvarsa, Object.createyaklaşımı kullanıyorsanız ve bunu sonra çağırmanız gerekirse bir yöntemi kesmek zorunda olmanız gerekir . newHer ikisini de yapan, prototip zincirini ayarlayan ve bazı başlatıcı kodu çağıran çok daha kolay .
Juan Mendes

67
Bunun kapalı olması gerektiğini düşünmüyorum. Evet, muhtemelen bazı Crockford anti-fan zehirine ilham verecek, ancak burada temel dil özelliklerinden kaçınmak için popüler tavsiyelerden bahsediyoruz. Her JQuery nesnesini (belleğin söz konusu olduğu yerlerde) neredeyse hiçbir şey tartmayan mekanizma 'yeni' anahtar kelimeyi kullanmayı içerir. Fabrika yöntemlerini sürekli olarak yeni olarak çağırmayı tercih edin, ancak yalnızca nesne değişmezlerini kullanarak mimari seçeneklerinizi ve performans potansiyelinizi önemli ölçüde azaltmayın. Onların yeri var ve inşaatçıların yeri var. Bu eller aşağı tarihli ve berbat tavsiye olduğunu.
Erik Reppen

2
TLDR: Kullanmak newtehlikeli değil. Atlamak newtehlikelidir ve bu nedenle kötüdür . Ancak ES5'te sizi bu tehlikeden ve diğerlerinden koruyan Sıkı Mod'u kullanabilirsiniz .
jkdev

Yanıtlar:


603

Crockford, iyi JavaScript tekniklerini popülerleştirmek için çok şey yaptı. Dilin kilit unsurları konusundaki görüşlü tutumu birçok yararlı tartışmaya yol açtı. Bununla birlikte, her bir "kötü" veya "zararlı" bildirisini müjde olarak alan ve bir adamın görüşünün ötesine bakmayı reddeden çok fazla insan var. Bazen biraz sinir bozucu olabilir.

newAnahtar kelime tarafından sağlanan işlevselliğin kullanımının, her bir nesneyi sıfırdan oluşturmanın birkaç avantajı vardır:

  1. Prototip mirası . Sınıf tabanlı OO dillerine alışkın olanlar tarafından sık sık şüphe ve alay konusu ele alınsa da, JavaScript'in yerel miras tekniği basit ve şaşırtıcı derecede etkili bir kod yeniden kullanımı aracıdır. Ve yeni anahtar kelime, kanonik (ve yalnızca mevcut platformlar arası) onu kullanma yöntemidir.
  2. Verim. Bu # 1 bir yan etkisidir: Ben oluşturmak her nesneye 10 yöntemleri eklemek istiyorsanız, ben olabilir sadece manuel her yeni nesneye her yöntemi atar bir yaratılış fonksiyon yazmak ... Ya ben onları atayabilirsiniz oluşturma işlevlerini prototypeve newyeni nesneleri damgalamak için kullanın . Bu sadece daha hızlı olmakla kalmaz (prototip üzerindeki her bir yöntem için kod gerekmez), her bir nesne için her nesnenin ayrı özelliklerle balonlanmasını önler. Daha yavaş makinelerde (veya özellikle daha yavaş JS tercümanlarında) çok sayıda nesne oluşturulduğunda bu, zaman ve bellekte önemli bir tasarruf anlamına gelebilir.

Ve evet, newdiğer cevaplar tarafından açıkça tanımlanan bir önemli dezavantajı var: Kullanmayı unutursanız, kodunuz uyarı vermeden kırılacaktır. Neyse ki, bu dezavantaj kolayca hafifletilebilir - sadece işlevin kendisine biraz kod ekleyin:

function foo()
{
   // if user accidentally omits the new keyword, this will 
   // silently correct the problem...
   if ( !(this instanceof foo) )
      return new foo();

   // constructor logic follows...
}

Artık newyanlışlıkla yanlış kullanımdan kaynaklanan sorunlar hakkında endişelenmenize gerek kalmadan avantajlara sahip olabilirsiniz. Hatta bozuk kod düşüncesinin sessizce sizi rahatsız edip etmediğini kontrol etmek için bir iddia da ekleyebilirsiniz. Veya bazılarının yorumladığı gibi, bir çalışma zamanı istisnası tanıtmak için bu denetimi kullanın:

if ( !(this instanceof arguments.callee) ) 
   throw new Error("Constructor called as a function");

(Bu snippet'in, yapıcı işlev adının sabit kodlanmasını önleyebileceğini unutmayın; önceki örnekten farklı olarak, nesneyi gerçekten başlatmaya gerek yoktur - bu nedenle, değişiklik yapılmadan her hedef işleve kopyalanabilir.)

John Resig, basit "Sınıf" Örnekleme gönderisinde bu teknikle ilgili ayrıntılara girer ve varsayılan olarak bu davranışı "sınıflarınıza" dahil etmenin bir yolunu da içerir. Kesinlikle bir oku ... onun yaklaşan kitap, olduğu gibi JavaScript Ninja Sırları Bu ve diğer pek çok "zararlı" altın gizlenmiş bulduğu, JavaScript dili özellikleri ( bölüm üzerinde withözellikle bizler için aydınlatmaktır başlangıçta görevden kim hile olarak bu çok kötü huylu özellik).


96
if (! (this instanceof arguments.callee)) Error ("Yapıcı işlev olarak adlandırılır"); // Genel olarak, yapıcıların adının bilinmesini gerektirmez, kullanıcının kodu düzeltmesini sağlayın.
bazı

5
Performans konusunda endişeliyseniz ve aslında nedeniniz varsa - o zaman kontrolü hiç yapmayın. Ya kullanmayı unutmayın newya da sizin için hatırlamak için bir sarmalayıcı işlevi kullanın. Ben şüpheli Eğer bu konularda noktada iseniz senin eserin aramaları ... Neyse lokalize olacak öyleyse, böyle memoization olarak zaten bitkin diğer optimizasyonlar getirdiğiniz
Shog9

65
Kullanılması arguments.calleeBirlikte çağırıldım olmadığını kontrol etmek newo kadar iyi olmayabilir, çünkü arguments.calleekatı modda kullanılamaz. İşlev adını kullanmak daha iyidir.
Sean McMillan

69
Bir tanımlayıcıyı yanlış yazarsam, kodum bozulur. Tanımlayıcı kullanmamalı mıyım? newKodunuzda yazmayı unutabileceğiniz için kullanmıyorum , benim örneğim kadar saçma.
Thomas Eding

16
Katı modda açarsanız eğer bunu kullanmaya çalıştığınızda bir istisna alacak yeni kullanmayı unutmayın: yuiblog.com/blog/2010/12/14/strict-mode-is-coming-to-town budur her kurucuya bir kontrol örneği eklemekten daha kolaydır.
stephenbez

182

Crockfords'ın "Javascript: The Good Parts" kitabının bazı bölümlerini okudum. Onu ısırmış her şeyi zararlı olarak gördüğü hissini alıyorum:

Hakkında geçiş hakkında:

Anahtar kasalarının bir sonraki davaya düşmesine asla izin vermem. Bir keresinde kodumda, düşmenin neden bazen yararlı olduğu konusunda güçlü bir konuşma yaptıktan hemen sonra istenmeyen bir düşüşün neden olduğu bir hata buldum. (sayfa 97, ISBN 978-0-596-51774-8)

++ ve - hakkında

++ (artış) ve - (azaltma) operatörlerinin, aşırı hileyi teşvik ederek kötü koda katkıda bulunduğu bilinmektedir. Virüsleri ve diğer güvenlik menülerini etkinleştirme konusunda yalnızca hatalı mimariden ikincisidirler. (sayfa 122)

Hakkında yeni:

Bir yapıcı işlevini çağırırken yeni öneki eklemeyi unutursanız , bu yeni nesneye bağlanmaz. Ne yazık ki, bu global nesneye bağlı olacaktır , bu nedenle yeni nesnenizi büyütmek yerine global değişkenleri zorlayacaksınız. Bu gerçekten kötü. Derleme uyarısı yoktur ve çalışma zamanı uyarısı yoktur. (sayfa 49)

Dahası var, ama umarım resmi alırsın.

Sorunuza cevabım: Hayır, zararlı değil. ancak eğer kullanmanız gerektiğinde kullanmayı unutursanız, bazı sorunlarınız olabilir. Eğer iyi bir ortamda gelişiyorsanız bunu fark edersiniz.

Güncelleme

Bu cevabın yazılmasından yaklaşık bir yıl sonra, ECMAScript'in 5. baskısı katı mod desteği ile yayınlandı . Katı modda, thisartık global nesneye bağlı değildir undefined.


3
Tamamen katılıyorum. Çözüm: Her zaman kullanıcıların nesnelerinizi nasıl somutlaştırmak zorunda olduklarını belgeleyin. Bir örnek kullanın ve kullanıcılar büyük olasılıkla keser / yapıştırır. Her dilde, olağandışı / beklenmedik davranışlara yol açacak şekilde yanlış kullanılabilen yapılar / özellikler vardır. Onları zararlı yapmaz.
nicerobot

45
Yapıcıları her zaman büyük harfle ve diğer tüm işlevleri küçük harfle başlatmak için bir kural vardır.
bazı

61
Crockford'un ZARARLIĞA ZARARLI olduğunu düşünmediğimi fark ettim ... Kaç kez sonsuz bir döngü oluşturduğumu bilmiyorum çünkü bir değişkeni artırmayı unuttum ...
bazı

5
Aynı şey ++, - için de geçerlidir. Niyetimi tam olarak mümkün olan en açık dilde ifade ediyorlar. Seviyorum! geçiş sonbahar bazıları için açık olabilir, ama ben bunlardan yorgunum. Onları açıkça daha net olduklarında kullanıyorum ('çünkü ceza, direnemedim).
PEZ

30
Crockford'a cevabım: Programlama zor, alışverişe gidelim. Sheesh!
Jason Jackson

91

Javascript dinamik dil olarak başka bir dilin sizi durduracağı bir milyon yol var.

Dağınık newolabileceğiniz gibi temel bir dil özelliğinden kaçınmak , bir mayın tarlasında yürümeden önce parlak yeni ayakkabılarınızı çıkarmak gibi, ayakkabılarınızı çamurlu tutabilirsiniz.

İşlev adlarının küçük harfle başladığı ve aslında sınıf tanımları olan 'işlevlerin' büyük harfle başladığı bir kural kullanıyorum. Sonuç 'sözdiziminin' yanlış olduğu konusunda oldukça ilgi çekici bir görsel ipucudur:

var o = MyClass();  // this is clearly wrong.

Bunun üzerine iyi adlandırma alışkanlıkları yardımcı olur. Tüm işlevlerden sonra bir şeyler yapar ve bu nedenle adında bir fiil olmalıdır, sınıflar nesneleri temsil eder ve fiilsiz isimler ve sıfatlardır.

var o = chair() // Executing chair is daft.
var o = createChair() // makes sense.

SO'nun sözdizimi renginin yukarıdaki kodu nasıl yorumladığı ilginç.


8
Evet, ben sadece sözdizimi renklendirmesi için de aynı şeyi düşünüyordum.
BobbyShaftoe

4
Bir kez 'fonksiyon' kelimesini yazmayı unuttum. Her ne pahasına olursa olsun bu kelimeden kaçınılmalıdır. Başka bir zaman ben / then deyiminde çok satırlı kıvırcık parantez kullanmadıysanız. Şimdi kıvırcık parantez kullanmıyorum ve sadece tek satırlık şartlar yazıyorum.
Hal50000

"Bu açıkça yanlış" . Neden? Sınıflarım için (ki basitçe if (! this instanceof MyClass) return new MyClass()) aslında new-less sözdizimini tercih ederim . Neden? Çünkü işlevler yapıcı işlevlerinden daha geneldir . Ayrılmak newyapıcı işlevini düzenli bir işleve dönüştürmeyi kolaylaştırır ... Ya da tam tersi. Eklemek newkodu olması gerekenden daha belirgin hale getirir. Ve böylece daha az esnek. Arayanın uygulamayı seçebilmesi için kabul Listedilmesi önerilen Java ile karşılaştırın ArrayList.
Stijn de Witt

41

Javascript için acemi değilim, belki de sadece bu iyi bir bakış açısı sağlama konusunda çok deneyimli değilim. Yine de bu "yeni" şey hakkındaki görüşümü paylaşmak istiyorum.

"Yeni" anahtar kelimesini kullanmanın o kadar doğal olduğu C # dünyasından geldim, bu bana garip görünen fabrika tasarım deseni.

Javascript ilk kod, YUI desen bir gibi "yeni" anahtar kelime ve kod olduğunu ve afete çalıştırmak için uzun sürmez farkında değilim. Ben yazdım kodu geri bakarken ne belirli bir satır ne yapması gerektiğini takip kaybeder. Daha karmakarışık kod "kuru çalışan" zaman aklım gerçekten nesne örnekleri sınırları arasında geçiş olamaz.

Sonra, "yeni" anahtar kelimeyi buldum, bu benim için "ayrı" şeyler. Yeni anahtar kelime ile bir şeyler yaratır. Yeni anahtar kelime olmadan, çağırdığım işlev bana bununla ilgili güçlü ipuçları vermediği sürece bir şeyler oluşturmakla karıştırmayacağımı biliyorum.

Örneğin, var bar=foo();hangi bar muhtemelen olabilir gibi hiçbir ipucu var .... Bu bir dönüş değeri mi yoksa yeni oluşturulan bir nesne mi? Ama var bar = new foo();biliyorum ki bar bir nesne.


3
Kabul ediyorum ve fabrika deseninin makeFoo () gibi bir adlandırma kuralına uyması gerektiğine inanıyorum
pluckyglen

3
+1 - 'yeni'nin varlığı daha net bir niyet beyanı verir.
belugabob

4
JS'deki hemen hemen her şey bir nesne olduğunda bu yanıt biraz gariptir. Neden tüm işlevler nesne olduğunda bir işlevin bir nesne olduğundan emin olmanız gerekir?
Joshua Ramirez

@JoshuaRamirez Mesele bu değil typeof new foo() == "object". Bunun newbir örneğini döndürür foove bilirsiniz foo.bar()ve foo.bang(). Ancak bu JsDoc's @return kullanarak kolayca hafifletilebilir Prosedürel kod için savunmak değilim (kelimeden kaçınarak new)
Juan Mendes

1
@JuanMendes Hmm ... Yayınınız, kod tabanınızdaki açık anahtar kelimesi nedeniyle yeni beğendiğinizi gösterdi. Bunu kazabilirim. Bu yüzden bir modül kalıbı kullanıyorum. CreateFoo veya NewFoo veya MakeFoo adında bir fonksiyonum olacak, açık olduğu sürece önemli değil. Bunun içinde, işlevden döndürülen bir nesne hazır bilgisi içinde kapanış olarak kullanılan değişkenleri bildiririm. Bu nesne değişmezi nesneniz olur ve işlev yalnızca bir inşaat işlevidir.
Joshua Ramirez

39

Başka bir durum için yeni ben dediğimiz Pooh Kodlama . Winnie the Pooh karnını takip ediyor. Gitmem demek ile , değil kullandığınız dilin karşı buna.

Büyük olasılıkla, dili koruyan kişiler dili teşvik etmeye çalıştıkları deyimler için optimize edeceklerdir. Dile yeni bir anahtar kelime koyarlarsa, muhtemelen yeni bir örnek oluştururken açık olmanın mantıklı olduğunu düşünürler.

Dilin niyetlerini takiben yazılan kod, her sürümde verimlilikte artacaktır. Ve dilin temel yapılarından kaçınan kod zamanla acı çekecektir.

EDIT: Ve bu performansın ötesine geçer. "Cehennem yaptıkları neden yaptığını Duydum kez saymak (veya adı geçen) olamaz o ?" garip görünümlü bir kod bulurken. Kodun yazıldığı sırada, bunun için "iyi" bir neden olduğu sık sık ortaya çıkıyor. Dilin Tao'yu takip etmek, kodunuzu birkaç yıl sonra alay etmediğiniz için en iyi sigortanızdır.


3
Pooh Kodlama bağlantısı için +1 - şimdi bu konuşmamda çalışmak için mazeretler bulmam gerekiyor ...
Shog9

LOL! Bu alanda yılların tecrübesine sahibim ve size hiçbir zorluk bulamayacağınızdan emin olabilirim. Sık sık bana robowiki.net adresinden Pooh diyorlar. =)
PEZ

1
Bu yorumu görüp görmeyeceğinizi bilmiyorum, ama Pooh Kodlama bağlantısı öldü.
Calvin

Söylediğin için teşekkürler. Geçen hafta robowiki.net'i yeni bir wikiye taşıdık ve şu an eski içeriğe erişilemiyor. Bu eski bağlantıların çalışmasını sağlamak için acele edeceğim.
PEZ

24

Yeni anahtar kelime olmadan bir kurucu çağırma sorununu nasıl azaltacağına dair bir yazı yazdım.
Çoğunlukla didaktiktir, ancak birlikte veya onsuz çalışan kurucuları nasıl oluşturabileceğinizi gösterir newve her kurucuda test etmek için kazan plakası kodu eklemenizi gerektirmez this.

http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

İşte tekniğin özü:

/**
 * Wraps the passed in constructor so it works with
 * or without the new keyword
 * @param {Function} realCtor The constructor function.
 *    Note that this is going to be wrapped
 *    and should not be used directly 
 */
function ctor(realCtor){
  // This is going to be the actual constructor
  return function wrapperCtor(){
    var obj; // object that will be created
    if (this instanceof wrapperCtor) {
      // Called with new
      obj = this;
    } else {
      // Called without new. Create an empty object of the
      // correct type without running that constructor
      surrogateCtor.prototype = wrapperCtor.prototype;
      obj = new surrogateCtor();
    }
    // Call the real constructor function
    realCtor.apply(obj, arguments);
    return obj;
  }

  function surrogateCtor() {}
}

Bunu nasıl kullanacağınız aşağıda açıklanmıştır:

// Create our point constructor
Point = ctor(function(x,y){
  this.x = x;
  this.y = y;
});

// This is good
var pt = new Point(20,30);
// This is OK also
var pt2 = Point(20,30);

6
kaçınmak arguments.calleeharika!
Gregg Lind

2
surrogateConstructorolmalıdır surrogateCtor(veya tersi).
David Conrad

Benzer Crockford'dan ilham alan yardımcı programlardan oluşan bir koleksiyon tuttum ve yeni bir projeye başladığımda uygulamaları bulmak için her zaman koştuğumu fark ettim. Bu da programlamanın bu kadar temel bir parçasını sarar: nesne somutlaştırma. Tüm bu çalışmalar, gelişigüzel örnekleme kodunu etkinleştirmek için mi? Bu ambalajın yaratıcılığını takdir ediyorum, ama sadece dikkatsiz kodlamaya yol açıyor gibi görünüyor.
Joe Coder

1
@joecoder Bunun sadece didaktik amaçlı olduğunu söylemiştim, bu paranoya kodlama stiline abone değilim. Ancak, bir sınıf kütüphanesi yazıyorsam, evet bu özelliği arayanlara şeffaf bir şekilde eklerdim
Juan Mendes

22

Yeni anahtar kelimeyi kullanmamanın ardındaki mantık basit:

Hiç kullanmamakla, yanlışlıkla atlayarak gelen tuzaklardan kaçınırsınız. YUI'nin kullandığı inşaat modeli, yeni anahtar kelimeyi nasıl tamamen önleyebileceğinize bir örnektir "

var foo = function () {
    var pub= { };
    return pub;
}
var bar = foo();

Alternatif olarak şunları yapabilirsiniz:

function foo() { }
var bar = new foo();

Ancak bunu yaparak, yeni anahtar kelimeyi kullanmayı unutan birinin riski vardır ve bu operatör tamamen fubar olur. AFAIK bunu yapmanın bir avantajı yoktur (alışık olduğunuzdan başka).

Günün Sonunda: Savunma olmakla ilgili. Yeni ifadeyi kullanabilir misiniz? Evet. Kodunuzu daha tehlikeli hale getiriyor mu? Evet.

C ++ yazdıysanız, işaretçileri sildikten sonra NULL değerine ayarlamak benzerdir.


6
Hayır. "New foo ()" ile, döndürülen nesne üzerinde yapıcı gibi bazı özellikler ayarlanır.
bazı

34
Yani, bunu açıklığa kavuşturmak için: “yeni” kullanmamalısınız, çünkü unutabilirsiniz? Şaka yapıyorsun değil mi?
Bombe

16
@Bombe: diğer dillerde "yeni" öğesinin unutulması hatayla sonuçlanır. Javascript'te, sadece kamyon taşımacılığına devam ediyor. Unutabilir ve asla fark edemezsiniz. Ve sadece erroroneous koduna bakarak alışkanlık yanlış giden tüm whats aşikardır.
Kent Fredric

3
@Greg: İlk tekniğin prototip zincirlerinin kullanımına nasıl izin verdiğini görmüyorum - nesne değişmezleri harika, ancak prototiplerin korkudan sağladığı performansı ve diğer avantajları atmak biraz aptalca görünüyor.
Shog9

5
@Bombe - Siz (ve kodunuzu kullanan herkes) hiçbir zaman hata yapmayacağınız için "yeni" kullanmalısınız? Şaka yapıyorsun değil mi?
Greg Dean

20

Bence "yeni" koda netlik katıyor. Ve netlik her şeye değer. Tuzaklar olduğunu bilmek güzel, ama açıklıktan kaçınarak onlardan kaçınmak benim için bir yol gibi görünmüyor.


16

Durum 1: newgerekli değildir ve kaçınılmalıdır

var str = new String('asd');  // type: object
var str = String('asd');      // type: string

var num = new Number(12);     // type: object
var num = Number(12);         // type: number

Durum 2: newgerekli, aksi takdirde bir hata alırsınız

new Date().getFullYear();     // correct, returns the current year, i.e. 2010
Date().getFullYear();         // invalid, returns an error

5
Durum 1'de yapıcıyı bir işlev olarak çağırmanın yalnızca tür dönüştürmeyi planlıyorsanız (ve gövde nesnesinin gibi bir dönüştürme yöntemine sahip olup olmadığını bilmiyorsanız) mantıklı olduğuna dikkat edilmelidir toString(). Diğer tüm durumlarda değişmez değerler kullanın. Değil String('asd') , ama basitçe 'asd've değil Number(12) , basitçe 12.
PointedEars

1
Bu kuralın bir istisnası Array: Array(5).fill(0) açıkçası daha okunabilir [undefined, undefined, undefined, undefined, undefined].fill(0)ve(var arr = []).length = 5; arr.fill(0);
yyny

@YoYoYonnY İfadem new, ilkel türlere karşılık gelen nesne türleri için yapıcılarla birlikte kullanılması anlamına gelen cevabın 1. durumu bağlamında yapılmıştır . Önerdiğiniz hazır bilgi çağrıyla eşdeğer değildirArray (deneyin 0 in …) ve geri kalanı bir sözdizimi hatasıdır :) Aksi takdirde haklısınız, ancak uygun olmayan uygulamaları Array(5)düşünürseniz belirsiz olabilir (ve bu nedenle taklit edilir ). Array.prototype.fill(…)
PointedEars

12

İşte, newoperatörün kullanımı için ve aleyhine en güçlü iki argümanın yapabileceği en kısa özet :

Karşıt arguman new

  1. newOperatör kullanılarak nesneler olarak başlatılması için tasarlanan işlevlerin, normal işlevler olarak yanlış çağrıldıklarında felaket etkileri olabilir. Böyle bir durumda bir işlevin kodu, amaçlandığı gibi yerel bir nesnenin kapsamı yerine, işlevin çağrıldığı kapsamda yürütülür. Bu, küresel değişkenlerin ve özelliklerin felaketle sonuçlanmasına neden olabilir.
  2. Son olarak, nesnenizi inşa etmek için çağırabileceğiniz function Func()ve yazarak bir Func.prototypeşeyler çağırıp ekleyerek new Func(), mimari ve stilistik nedenlerle başka bir nesne mirası stili kullanmayı tercih eden bazı programcılar için çirkin görünüyor.

Bu argüman hakkında daha fazla bilgi için Douglas Crockford'un harika ve özlü kitabı Javascript: The Good Parts'a göz atın. Aslında yine de kontrol edin.

Lehine tartışma new

  1. Kullanmak new Prototypal atama ile birlikte operatöre hızlı.
  2. Bir yapıcı işlevinin kodunu genel ad alanında yanlışlıkla çalıştırmayla ilgili şeyler, yapıcı işlevlerinize her zaman doğru bir şekilde çağrılıp çağrılmadığını kontrol etmek için her zaman bir miktar kod eklerseniz kolayca engellenebilir ve , çağrıyı istediğiniz gibi uygun şekilde yönetme.

Bu tekniğin basit bir açıklaması ve savunduğu kalıtım modelinin genel olarak daha derin bir açıklaması için John Resig'in görevine bakınız .


Argümanlar karşı ilgili bir güncelleme: 1. kullanılarak hafifletilebilir 'use strict';modu (veya bağlantı yöntemi) # 2'de synatic şeker Has ES6 ancak davranış önceki ile aynı olduğunu.
ninMonkey

9

Pez ve bazılarına katılıyorum.

Bana göre "yeni" nin, Greg Dean'in tanımladığı YUI modelinin tamamen gizlendiği kendini tanımlayıcı bir nesne yaratımı olduğu açık .

Birinin yazabileceği var bar = foo;veya var bar = baz();bazın bir nesne oluşturma yöntemi olmadığı olasılığı çok daha tehlikeli görünüyor .


8

Yeni bir şey kötü olduğunu düşünüyorum, çünkü yanlışlıkla kullanmayı unutursanız sorunlara neden olabilir, ancak miras zincirini bozduğundan, dili anlamak daha zor hale gelir.

JavaScript prototip tabanlı nesne yönelimlidir. Bu nedenle her nesne böyle bir nesneden oluşturulmalıdır ZORUNLU var newObj=Object.create(oldObj). İşte oldObj prototipi denir newObj (dolayısıyla "prototip tabanlı"). Bu, bir özellik newObj içinde bulunmazsa , oldObj'de aranacağını gösterir . Bu nedenle , varsayılan olarak newObj boş bir nesne olacaktır, ancak prototip zinciri nedeniyle tüm oldObj değerlerine sahip gibi görünmektedir .

Bunu yaparsanız Öte yandan var newObj=new oldObj(), prototipi newObj olan oldObj.prototype anlamak gereksiz yere zordur.

Hile kullanmak

Object.create=function(proto){
  var F = function(){};
  F.prototype = proto;
  var instance = new F();
  return instance;
};

Bu fonksiyonun içindedir ve sadece burada yeni kullanılmalıdır. Bundan sonra sadece Object.create () yöntemini kullanın. Yöntem, prototip sorununu çözer.


7
Dürüst olmak gerekirse, bu teknik hakkında çılgın değilim - yeni bir şey eklemiyor ve cevabınızın gösterdiği gibi bir koltuk değneği bile olabilir. IMHO, prototip zincirlerini ve nesne somutlaştırmasını anlamak JavaScript'i anlamak için çok önemlidir ... Ancak bunları doğrudan kullanmanız sizi rahatsız ediyorsa, bazı ayrıntılara dikkat etmek için yardımcı bir işlev kullanmak iyidir, ne olduğunuzu hatırladığınız sürece yapıyor. FWIW: Bu konuda (biraz daha yararlı) bir varyasyon ECMAScript 5. baskıda yer almaktadır. std ve bazı tarayıcılarda zaten mevcut - bu yüzden körü körüne yeniden tanımlamamaya dikkat etmelisiniz!
Shog9

BTW: Bu CW'yi neden yaptığınızdan emin değilim, ancak yaptığım biçimlendirme düzeltmeleriyle yeniden göndermek istiyorsanız, bu onay kutusundan kaçınmaya dikkat edin ...
Shog9

2
Gereksiz yere anlamak zor mu? var c = new Car()yapmakla aynıdırvar c = Object.create(Car.prototype); Car.call(c)
Juan Mendes
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.