Prototip oluştururken yapıcıların kullanımı neden önerilmez?


10

Hızlı arka plan: JavaScript'te, her nesne türü için yapıcı işlevinin bir prototypeözelliği vardır. Bu prototype, her bir yapılandırılmış nesnenin, prototip zincirinde bir sonraki adım olarak kullandığı bir nesneyi ifade eder. Bir türün başka bir türden içsel olmasını istediğinizde prototype, alt türün üst türünün yeni bir örneğine ayarlayabilirsiniz .

Örneğin:

var Parent = function() { /* constructor business */ }
Parent.prototype.parentProp = "some parent property";

var Child = function() { /* constructor business */ }
Child.prototype = /*** !! Some prototype object goes here !! ***/

Benim sorum Some prototype object goes hereyukarıdaki kod " " yerinde hangi kod gitmek gerektiğini sorar . İlk içgüdüm, ebeveynin bir örneğini (yani, new Parent()) oluşturmak, ancak bir cevabın yorumunda bu, bir nesne prototipini diğerine kopyalamanın güvenli bir yolu mu? , bir kullanıcı şunu yazar:

Hayır, new bar()prototip nesnesi için kullanmayın !

(... bu, birçok SO yanıtı ve yorumunda gördüğüm bir görüş, ancak şu anda elimde olan tek örnek bu.)

Diğer seçenek kullanıma etmektir Object.create(Parent.prototype)olarak Child.prototype. Bildiğim kadarıyla, bu da yeni bir Parentörnek oluşturur , ancak yapıcıyı çalıştırmaz Parent.

Birisi üst türden bir prototip nesnesi oluştururken yapıcı işlevini çalıştırmaktan neden kaçınılması gerektiğini açıklayabilir mi? Ortaya çıkan önemli bir teknik sorun var mı (belki birden fazla miras ile)? Ya da böyle bir model, bazı prototipik en iyi uygulamalarla çatışan kurucuların yanlış kullanımı mıdır (örneğin, bir prototip oluştururken kurucuyu çalıştırmak endişelerin ayrılmasını ihlal eder)?

Yanıtlar:


5

Çünkü çağrılması gerekmeyen bir işlev. newJavascript'teki normal işlev çağrısından farklı değildir.

Bir kurucu, alanları ayarlamaktan daha fazlasını yapabilir. Örneğin, gelen verileri doğrularsa, yalnızca devralma zincirini ayarlamaya çalıştığınızda bir doğrulama hatasına neden olursunuz.

Ve ihtiyacınız yok Object.create, bu yeterli:

function objectCreate( proto ) {
    function T(){}
    T.prototype = proto;
    return new T();
}

Ancak tam da böyle Object.createuygulanmaktadır.
Casey Chu

@CaseyChu hiç de değil. Ve bağlantılı yazıda birisi " Object.createIE8'de çalışmaz " dediğinden bahsettim - bu, herhangi bir tarayıcıda 2 saniye içinde bu kullanım durumu için uygulayabildiğinizde işe yaramaz bir yorum.
Esailija

2

Anlayışım biraz genişlediğine göre, Esailija'nın cevabını belirli bir örnekle inşa etmek istiyorum :

Özel bir endişe, bir kurucu örneğe özgü özellikleri ayarlayabilir olmasıdır. Bu nedenle, ile oluşturulan bir prototip nesnesi kullanırsanız new, tüm alt örnekleriniz prototipten yapıcı tanımlı tek bir örneğe özgü özelliği paylaşabilir.

Örneğin, Parentörneklerin her birinin idinşaat süresi olarak ayarlanmış benzersiz bir özelliği olduğunu varsayalım :

var Parent = function() { this.id = Math.random(); }
Parent.prototype.parentProp = "some parent property";

var Child = function() { /* constructor business */ }
Child.prototype = new Parent();

Bu, tüm Child örneklerin, kullanılan idtek new Parent()nesneden miras alınan tek bir prototip özelliğini paylaşmasına neden olur Child.prototype.

Bu durum için daha iyi bir yaklaşım Object.create, alt kurucu içindeki üst kurucuyu (gerekirse) kullanmak ve doğrudan çağırmaktır:

var Parent = function() { this.id = Math.random(); }
Parent.prototype.parentProp = "some parent property";

var Child = function() {
    // run `this` through the Parent constructor function
    Parent.apply(this, arguments);
}
Child.prototype = Object.create(Parent.prototype);
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.