Bu kalıbı epeyce Node.js kitaplığında görüyorum:
Master.prototype.__proto__ = EventEmitter.prototype;
(kaynak burada )
Birisi bana bir örnekle açıklayabilir mi, bunun neden bu kadar yaygın bir model olduğunu ve ne zaman kullanışlı olduğunu?
Bu kalıbı epeyce Node.js kitaplığında görüyorum:
Master.prototype.__proto__ = EventEmitter.prototype;
(kaynak burada )
Birisi bana bir örnekle açıklayabilir mi, bunun neden bu kadar yaygın bir model olduğunu ve ne zaman kullanışlı olduğunu?
__proto__
bir anti-modeldir, lütfen kullanınMaster.prototype = Object.create(EventEmitter.prototype);
util.inherits(Master, EventEmitter);
Yanıtlar:
Kodun yukarısındaki yorumda belirtildiği gibi, bu koddan Master
miras alacak EventEmitter.prototype
, böylece olayları yaymak ve dinlemek için bu 'sınıfın' örneklerini kullanabilirsiniz.
Örneğin şimdi yapabilirsiniz:
masterInstance = new Master();
masterInstance.on('an_event', function () {
console.log('an event has happened');
});
// trigger the event
masterInstance.emit('an_event');
Güncelleme : Birçok kullanıcının belirttiği gibi, bunu Node'da yapmanın 'standart' yolu 'util.inherits' kullanmak olacaktır:
var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);
2. Güncelleme : ES6 sınıfları ile birlikte, EventEmitter
sınıfı şimdi genişletmeniz önerilir :
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
require('events').EventEmitter
her zaman unutuyorum. Başkasının ihtiyacı olması durumunda dokümanlar için bağlantı burada: nodejs.org/api/events.html#events_class_events_eventemitter )
MasterInstance
olmalıdır masterInstance
.
Master.prototype = EventEmitter.prototype;
. Süperlere gerek yok. ES6 uzantılarını da bu şekilde kullanabilirsiniz (ve Node.js belgelerinde teşvik edilmektedir util.inherits
) class Master extends EventEmitter
- klasik olursunuz super()
, ancak içine herhangi bir şey enjekte etmeden Master
.
Düğüm belgeleri artık kendi olay yayıcınızı oluşturmak için sınıf mirasını kullanmanızı öneriyor :
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {
// Add any custom methods here
}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
Not:constructor()
içinde bir işlev tanımlarsanız MyEmitter
, bunu super()
yapmamak için iyi bir nedeniniz yoksa, ana sınıfın kurucusunun da çağrılmasını sağlamak için ondan çağırmalısınız .
super()
yapmak gerekli değildir, bu nedenle Breedly'nin orijinal cevabı (bkz.DÜZENLE geçmişi) tamamen doğrudur. Bu durumda, bu aynı örneği kopyaya kopyalayıp yapıştırabilir, kurucuyu tamamen kaldırabilirsiniz ve aynı şekilde çalışacaktır. Bu mükemmel bir sözdizimidir.
Başka bir Javascript nesnesinden, özellikle Node.js'nin EventEmiter'ından, ancak gerçekten herhangi bir nesneden miras almak için iki şey yapmanız gerekir:
[[proto]]
yapıcınızdan oluşturulan nesneler için kullanılacak bir prototip nesnesi sağlayın; Başka bir nesneden miras aldığınız durumda, muhtemelen prototipiniz olarak diğer nesnenin bir örneğini kullanmak istersiniz.Bu, Javascript'te diğer dillerde göründüğünden daha karmaşıktır çünkü
Node.js'nin EventEmiter'ının özel durumu için şu şekilde çalışır:
var EventEmitter = require('events').EventEmitter;
var util = require('util');
// Define the constructor for your derived "class"
function Master(arg1, arg2) {
// call the super constructor to initialize `this`
EventEmitter.call(this);
// your own initialization of `this` follows here
};
// Declare that your class should use EventEmitter as its prototype.
// This is roughly equivalent to: Master.prototype = Object.create(EventEmitter.prototype)
util.inherits(Master, EventEmitter);
Olası zayıflıklar:
util.inherits
, alt sınıfınız için prototipi (Master.prototype) belirlerseniz, ancak EventEmitter
sınıfınızın örnekleri için süper yapıcıyı () çağırmazsanız , bunlar düzgün şekilde başlatılmaz.new EventEmitter
) başlatılmış bir örneğini kullanmayı deneyebilirsiniz ; bir süre iyi çalışıyormuş gibi görünen ancak aynı şey olmayan (ve EventEmitter için çalışmayacak) süper sınıf kurucusunun davranışına bağlı olarak.Master.prototype
Master
EventEmitter
Master.prototype = EventEmitter.prototype
Object.create aracılığıyla ek bir nesne katmanı eklemek yerine süper prototipi doğrudan ( ) kullanmayı deneyebilirsiniz; Bu, birisi nesnenizi Master
maymunla eşleştirene EventEmitter
ve istemeden maymun eki ve diğer tüm soyundan gelenlere kadar iyi çalışıyormuş gibi görünebilir . Her "sınıf" kendi prototipine sahip olmalıdır.Yine: EventEmitter'dan (veya gerçekten mevcut herhangi bir nesne "sınıfından") miras almak için, süper kurucuyu zincirleyen ve süper prototipten türetilen bir prototip sağlayan bir kurucu tanımlamak istersiniz.
JavaScript'te prototip (prototip?) Kalıtım bu şekilde yapılır. Gönderen MDN'yi :
Nesne veya boş olabilen nesnenin prototipini ifade eder (bu genellikle nesnenin prototipi olmayan Object.prototype olduğu anlamına gelir). Bazen prototip mirasına dayalı özellik aramasını uygulamak için kullanılır.
Bu da işe yarar:
var Emitter = function(obj) {
this.obj = obj;
}
// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
JavaScript OOP'yi anlamak , ECMAScript 5'te OOP'ta son zamanlarda okuduğum en iyi makalelerden biridir.
Y.prototype = new X();
bir anti-desen, lütfen kullanınY.prototype = Object.create(X.prototype);
new X()
bir örneğini somutlaştırır X.prototype
ve onu çağırarak onu başlatır X
. Object.create(X.prototype)
sadece bir örnek oluşturur. İlklendirilmek istemezsin Emitter.prototype
. Bunu açıklayan iyi bir makale bulamıyorum.
Http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm'deki bu yaklaşımın oldukça düzgün olduğunu düşündüm :
function EventedObject(){
// Super constructor
EventEmitter.call( this );
return( this );
}
Douglas Crockford da bazı ilginç kalıtım kalıplarına sahiptir: http://www.crockford.com/javascript/inheritance.html
JavaScript ve Node.js'de kalıtıma daha az ihtiyaç duyulduğunu görüyorum. Ancak, kalıtımın ölçeklenebilirliği etkileyebileceği bir uygulama yazarken, performansın sürdürülebilirliğe karşı tartıldığını düşünürdüm. Aksi takdirde, kararımı yalnızca hangi modellerin daha iyi genel tasarımlara yol açtığına, daha sürdürülebilir olduğuna ve daha az hata yapmaya yatkın olduğuna dayandırırım.
Kabaca bir karşılaştırma elde etmek için Google Chrome'u (V8) kullanarak jsPerf'de farklı desenleri test edin. V8, hem Node.js hem de Chrome tarafından kullanılan JavaScript motorudur.
İşte başlamanıza yardımcı olacak bazı jsPerfs:
http://jsperf.com/prototypes-vs-functions/4
emit
ve on
tanımlanmamış olarak geliyor.
Wprl'nin cevabına eklemek için. "Prototip" kısmını kaçırdı:
function EventedObject(){
// Super constructor
EventEmitter.call(this);
return this;
}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part
util.inherits
çünkü birçok akıllı insan bu seçenekleri sizin için güncel tutacaktır.