Saya melihat pola ini di beberapa perpustakaan Node.js:
Master.prototype.__proto__ = EventEmitter.prototype;
(sumber di sini )
Bisakah seseorang menjelaskan kepada saya dengan sebuah contoh, mengapa ini adalah pola yang umum dan kapan itu berguna?
node.js
eventemitter
jeffreyveon
sumber
sumber
__proto__
adalah anti-pola, silakan gunakanMaster.prototype = Object.create(EventEmitter.prototype);
util.inherits(Master, EventEmitter);
Jawaban:
Seperti komentar di atas yang dikatakan kode itu, itu akan membuat
Master
warisan dariEventEmitter.prototype
, sehingga Anda dapat menggunakan contoh dari 'kelas' itu untuk memancarkan dan mendengarkan acara.Misalnya sekarang Anda dapat melakukan:
masterInstance = new Master(); masterInstance.on('an_event', function () { console.log('an event has happened'); }); // trigger the event masterInstance.emit('an_event');
Pembaruan : seperti yang ditunjukkan oleh banyak pengguna, cara 'standar' untuk melakukan itu di Node adalah menggunakan 'util.inherits':
var EventEmitter = require('events').EventEmitter; util.inherits(Master, EventEmitter);
Pembaruan ke-2 : dengan kelas ES6 pada kami, disarankan untuk memperluas
EventEmitter
kelas sekarang:const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event');
Lihat https://nodejs.org/api/events.html#events_events
sumber
require('events').EventEmitter
dulu-- Saya selalu lupa. Berikut tautan ke dokumen jika ada orang lain yang membutuhkannya: nodejs.org/api/events.html#events_class_events_eventemitter )MasterInstance
seharusnyamasterInstance
.util.inherits
melakukan hal yang buruk dengan memasukkansuper_
properti ke dalamMaster
objek. Ini tidak perlu dan mencoba memperlakukan warisan prototipe seperti warisan klasik. Lihat di bagian bawah halaman ini untuk penjelasan.Master.prototype = EventEmitter.prototype;
. Tidak perlu supers. Anda juga dapat menggunakan ES6 extends (dan didorong di dokumen Node.js onutil.inherits
) seperti iniclass Master extends EventEmitter
- Anda mendapatkan versi klasiksuper()
, tetapi tanpa memasukkan apa pun ke dalamnyaMaster
.Pewarisan Kelas Gaya ES6
Dokumen Node sekarang merekomendasikan penggunaan class inheritence untuk membuat event emitter Anda sendiri:
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');
Catatan: Jika Anda mendefinisikan sebuah
constructor()
fungsi diMyEmitter
, Anda harus memanggilnyasuper()
untuk memastikan konstruktor kelas induk juga dipanggil, kecuali Anda punya alasan kuat untuk tidak melakukannya.sumber
super()
yang tidak diperlukan , selama Anda tidak perlu / mendefinisikan konstruktor, maka jawaban asli Breedly (lihat sejarah EDIT) adalah sepenuhnya benar. Dalam hal ini Anda dapat menyalin dan menempel contoh yang sama ini di repl, menghapus konstruktor seluruhnya dan itu akan bekerja dengan cara yang sama. Itu adalah sintaks yang benar-benar valid.Untuk mewarisi dari objek Javascript lain, EventEmitter Node.js secara khusus tetapi sebenarnya objek apa pun secara umum, Anda perlu melakukan dua hal:
[[proto]]
untuk objek yang dibuat dari konstruktor Anda; dalam hal Anda mewarisi dari beberapa objek lain, Anda mungkin ingin menggunakan instance dari objek lain sebagai prototipe Anda.Ini lebih rumit di Javascript daripada yang terlihat di bahasa lain karena
Untuk kasus spesifik EventEmitter Node.js, inilah yang berhasil:
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);
Kelemahan yang mungkin:
util.inherits
, tetapi tidak memanggil super constructor (EventEmitter
) untuk instance kelas Anda, mereka tidak akan diinisialisasi dengan benar.new EventEmitter
) sebagaiMaster.prototype
ganti meminta konstruktor subclassMaster
memanggil super konstruktorEventEmitter
; tergantung pada perilaku konstruktor superclass yang mungkin tampak berfungsi dengan baik untuk sementara waktu, tetapi bukan hal yang sama (dan tidak akan berfungsi untuk EventEmitter).Master.prototype = EventEmitter.prototype
) daripada menambahkan lapisan objek tambahan melalui Object.create; ini mungkin tampak berfungsi dengan baik sampai seseorang mencocokkan objek AndaMaster
dan secara tidak sengaja juga mencocokkan monkeypatchEventEmitter
dan semua turunan lainnya. Setiap "kelas" harus memiliki prototipe sendiri.Sekali lagi: untuk mewarisi dari EventEmitter (atau objek "kelas" yang sebenarnya), Anda ingin menentukan konstruktor yang terhubung ke konstruktor super dan menyediakan prototipe yang diturunkan dari super prototipe.
sumber
Beginilah cara pewarisan prototipe (prototypal?) Dilakukan di JavaScript. Dari MDN :
Ini bekerja juga:
var Emitter = function(obj) { this.obj = obj; } // DON'T Emitter.prototype = new require('events').EventEmitter(); Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
Memahami JavaScript OOP adalah salah satu artikel terbaik yang saya baca akhir-akhir ini di OOP di ECMAScript 5.
sumber
Y.prototype = new X();
adalah anti-pola, silakan gunakanY.prototype = Object.create(X.prototype);
new X()
membuat instance dariX.prototype
dan menginisialisasinya dengan memanggilnyaX
.Object.create(X.prototype)
hanya membuat contoh. Anda tidak inginEmitter.prototype
diinisialisasi. Saya tidak dapat menemukan artikel bagus yang menjelaskan hal ini.Saya pikir pendekatan dari http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm ini cukup rapi:
function EventedObject(){ // Super constructor EventEmitter.call( this ); return( this ); }
Douglas Crockford juga memiliki beberapa pola pewarisan yang menarik: http://www.crockford.com/javascript/inheritance.html
Saya menemukan bahwa inheritence jarang dibutuhkan di JavaScript dan Node.js. Namun dalam menulis aplikasi yang pewarisannya dapat memengaruhi skalabilitas, saya akan mempertimbangkan performa yang dibandingkan dengan pemeliharaan. Jika tidak, saya hanya akan mendasarkan keputusan saya pada pola mana yang mengarah pada desain keseluruhan yang lebih baik, lebih mudah dirawat, dan tidak terlalu rentan terhadap kesalahan.
Uji pola yang berbeda di jsPerf, menggunakan Google Chrome (V8) untuk mendapatkan perbandingan kasar. V8 adalah mesin JavaScript yang digunakan oleh Node.js dan Chrome.
Berikut ini beberapa jsPerf untuk Anda mulai:
http://jsperf.com/prototypes-vs-functions/4
http://jsperf.com/inheritance-proto-vs-object-create
http://jsperf.com/inheritance-perf
sumber
emit
danon
muncul sebagai tidak terdefinisi.Untuk menambah respon wprl. Dia melewatkan bagian "prototipe":
function EventedObject(){ // Super constructor EventEmitter.call(this); return this; } EventObject.prototype = new EventEmitter(); //<-- you're missing this part
sumber
util.inherits
karena banyak orang pintar akan terus memperbarui opsi tersebut untuk Anda.