Soru Node.js - EventEmitter'dan devralınması


Bu deseni birkaç Node.js kütüphanesinde görüyorum:

Master.prototype.__proto__ = EventEmitter.prototype;

(kaynak İşte)

Birisi bana bir örnekle açıklayabilir mi, neden bu yaygın bir desen ve ne zaman kullanışlı?


76
2018-01-17 16:44


Menşei


Bilgi için bu soruya bakın stackoverflow.com/questions/5398487/... - Juicy Scripter
Not __proto__ bir anti-desen, lütfen kullanın Master.prototype = Object.create(EventEmitter.prototype); - Raynos
Aslında, kullan util.inherits(Master, EventEmitter); - thesmart
@Raynos Bir anti-desen nedir? - starbeamrainbowlabs
Bu, ES6 Sınıfı kurucularla artık daha kolay. Buradaki uyumu kontrol et: kangax.github.io/compat-table/es6 . Aşağıdaki dokümanları veya cevabımı kontrol edin. - Breedly


Cevaplar:


Yukarıdaki kodun söylediği gibi, Master miras kalmak EventEmitter.prototypeBöylece olayları yaymak ve dinlemek için o sınıfın örneklerini kullanabilirsiniz.

Örneğin şimdi yapabileceğiniz:

masterInstance = new Master();

masterInstance.on('an_event', function () {
  console.log('an event has happened');
});

// trigger the event
masterInstance.emit('an_event');

Güncelleştirme: Pek çok kullanıcı işaret ettiği gibi, Node'da bunu yapmanın 'standart' yolu 'util.inherits' kullanmak olacaktır:

var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);

77
2018-01-17 16:54



(sadece küçük bir hatırlatma yapmak require('events').EventEmitter ilk önce her zaman unutacağım. Başka birinin buna ihtiyacı olduğunda dokümanlar için bağlantı: nodejs.org/api/events.html#events_class_events_eventemitter) - mikermcneil
BTW, örneklerin sözleşmesi ilk harfi küçük harfle yazmaktır. MasterInstance olmalı masterInstance. - khoomeister
Ve aşağıdakileri kontrol etme yeteneğini nasıl koruyorsunuz: MasterInstance Master? - jayarjo
util.inherits enjekte iğrenç bir şey super_ özellik içine Master nesne. Gereksizdir ve klasik kalıtım gibi prototipik mirasları tedavi etmeye çalışır. Dibine bir göz atın bu açıklama sayfası. - Killah
@loretoparisi sadece Master.prototype = EventEmitter.prototype;. Üstüne gerek yok. Ayrıca ES6 uzantılarını da kullanabilirsiniz (ve Node.js belgelerinde util.inherits) bunun gibi class Master extends EventEmitter - klasik olsun super()ama içine hiçbir şey enjekte etmeden Master. - Killah


ES 6 Stil Sınıfı Kalıtım

Bunlar doğrudan dokümanlardan geliyor, ama bu popüler soruya onları arayan herkese eklemek güzel olurdu.

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {
  constructor() {
    super(); //must call super for "this" to be defined.
  }     
}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

isterdim git thank Bunu ekleyen kişi. Etkinlik Verici.

Not: Belgeler çağırmaz super() neden olacak kurucu this undefined olmak. Bunu gör konu.


56
2018-03-11 16:22



MyEmitter sınıfı EventEmitter {constructor () {super (); // tanımlanacak "bu" için süper çağırmalı. }} `` ` - Chase Wilson
En iyi cevap, ama bir hata var: super() kurucuda olmalı. Lütfen düzeltin. - Firanolfind
Bu yorumlar doğru değildir ve bu durumda yanıltıcıdır. çağrı super() olduğu gerekli değilBir kurucuya ihtiyaç duymadığınız / tanımlamadığınız sürece, Breedly'nin orijinal cevabı (DÜZENLEME geçmişine bakın) tamamen doğruydu. Bu durumda bu aynı örneği kopyaya kopyalayıp yapıştırabilir, kurucuyu tamamen kaldırabilir ve aynı şekilde çalışacaktır. Bu mükemmel bir geçerli sözdizimi. - Nobita


Başka bir Javascript nesnesinden devralmak için, Node.js'in EventEmitter'i özellikle de gerçekten herhangi bir nesne olarak iki şey yapmalısınız:

  • Nesneyi tamamen başlatan nesneyiniz için bir kurucu sağlayın; Başka bir nesneden miras aldığınız durumda, muhtemelen bu başlatma çalışmalarının bir kısmını süper kurucuya devretmek istersiniz.
  • olarak kullanılacak bir prototip nesne sağlamak [[proto]] kurucunuzdan oluşturulan nesneler için; 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ü

  • Javascript, nesne davranışını "kurucu" ve "prototip" olarak ayırır. Bu kavramlar birlikte kullanılmaya yöneliktir, ancak ayrı olarak kullanılabilir.
  • Javascript çok biçimlendirilebilir bir dildir ve insanlar bunu farklı kullanırlar ve "miras" ın ne anlama geldiğinin tek bir gerçek tanımı yoktur.
  • Birçok durumda, doğru olanın bir alt kümesini yaparak uzaklaşabilirsiniz ve durumunuz için iyi çalışıyor gibi görünecek tonlarca örnek (bu SO sorusuna verilen diğer cevaplar dahil) bulacaksınız.

Node.js'in EventEmitter özel durumu için, aşağıdakiler işe yarar:

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ı folaları:

  • Alt sınıfınızın (Master.prototype) prototipini, kullanıp kullanmayacağınızı veya kullanmadan kullanırsanız util.inheritsama süper kurucuyu aramayın (EventEmitter) sınıfınızın örnekleri için, düzgün bir şekilde başlatılmayacaklardır.
  • Süper kurucuyu çağırırsanız ancak prototip belirlemezseniz, EventEmitter yöntemleri nesnenizde çalışmayacaktır.
  • Üst sınıfın başlatılmış örneğini kullanmaya çalışabilirsiniz (new EventEmitter) gibi Master.prototype alt sınıf kurucusuna sahip olmak yerine Master süper kurucuyu ara EventEmitter; Bir süre için iyi çalışıyor gibi görünebilir, ancak aynı şey değildir (ve EventEmitter için çalışmayacak) süper sınıfı kurucusunun davranışına bağlı olarak.
  • Süper prototipi doğrudan kullanmayı deneyebilirsiniz (Master.prototype = EventEmitter.prototypeObject.create ile ek bir nesne katmanı eklemek yerine; Bu, birisi nesneyi maymunpatch edene kadar iyi çalışıyor gibi görünebilir Master ve yanlışlıkla da maymunculu EventEmitter ve diğer tüm torunları. Her "sınıf" kendi prototipine sahip olmalıdır.

Yine: EventEmitter'den (veya gerçekten var olan herhangi bir nesne "sınıfından") miras almak için, süper yapıcıya zincir oluşturan ve süper prototipten türetilen bir prototip sağlayan bir kurucu tanımlamak istersiniz.


36
2018-05-28 17:55





Prototipik (prototypal?) Kalıtımın JavaScript'te nasıl yapıldığı budur. itibaren MDN:

Nesne veya null olabilecek nesnenin prototipini ifade eder.   (Bu genellikle nesnenin Object.prototype olduğu anlamına gelir.   prototip). Bazen prototip-mirasın uygulanmasında kullanılır   özellik arama özelliği.

Bu da çalışır:

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 anlama ECMAScript 5'te son zamanlarda okuduğum en iyi makalelerden biri.


19
2018-01-17 16:55



Y.prototype = new X(); bir anti-desen, lütfen kullanın Y.prototype = Object.create(X.prototype); - Raynos
Bu bilmek güzel. Daha fazla yer okuyabilir miyim? Ortaya çıkan nesnelerin farklı olmasıyla ilgilenir. - Daff
new X() bir örneğini örneklemek X.prototype ve invoke ederek başlatır X üstünde. Object.create(X.prototype) sadece bir örneği örneklendirir. Sen yoksun Emitter.prototype başlatılacak. Bunu açıklayan iyi bir makale bulamıyorum. - Raynos
Bu mantıklı. İşaret ettiğin için teşekkürler. Hala Node'da iyi alışkanlıklara girmeye çalışıyor. Tarayıcılar sadece ECMA5 için orada değil (ve anladığım kadarıyla en güvenilir olanı değil). - Daff
Diğer bağlantı da bozuk. Bunu dene: robotlolita.github.io/2011/10/09/... - jlukanta


Bu yaklaşımı düşündüm http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm oldukça düzgün:

function EventedObject(){

  // Super constructor
  EventEmitter.call( this );

  return( this );

}

Douglas Crockford'un da bazı ilginç miras kalıpları var: http://www.crockford.com/javascript/inheritance.html

Javascript ve Node.js. daha az sıklıkta ihtiyaç duyduğumu buluyorum. Ancak, kalıtsallığın ölçeklenebilirliği etkileyebileceği bir uygulama yazarken, performansın sürdürülebilirliğe karşı ağırlığını düşünebilirim. Aksi takdirde, sadece hangi modellerin daha iyi genel tasarımlara yol açtığına, daha fazla sürdürülebileceğine ve daha az hataya açık olduğuna karar vereceğim.

Kaba bir karşılaştırma elde etmek için Google Chrome'u (V8) kullanarak jsPerf'te farklı modelleri test edin. V8, Node.js ve Chrome tarafından kullanılan JavaScript motorudur.

İşte size başlamak için bazı jsPerfs:

http://jsperf.com/prototypes-vs-functions/4

http://jsperf.com/inheritance-proto-vs-object-create

http://jsperf.com/inheritance-perf


5
2018-03-01 16:50



Bu yaklaşımı denedim ve emit ve on undefined olarak geliyorlar. - dopatraman
Dönüş (bu) değil mi; sadece zincirleme için mi? - blablabla


Wprl'nin yanıtına eklemek için. "Prototip" bölümünü kaçırdı:

function EventedObject(){

   // Super constructor
   EventEmitter.call(this);

   return this;

}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part

1
2018-06-03 20:47



Aslında, yeni yerine Object.create kullanmalısınız, aksi halde örnek durumu ve prototip üzerinde açıklandığı gibi başka yerde. Ama ES6'yı kullanmak ve transpile etmek veya util.inherits Çok sayıda akıllı insan bu seçenekleri sizin için güncel tutacaktır. - Cool Blue