मैं इस पैटर्न को कुछ Node.js पुस्तकालयों में देखता हूं:
Master.prototype.__proto__ = EventEmitter.prototype;
( यहां स्रोत )
क्या कोई मुझे एक उदाहरण के साथ समझा सकता है, यह इतना सामान्य पैटर्न क्यों है और जब यह आसान है?
मैं इस पैटर्न को कुछ Node.js पुस्तकालयों में देखता हूं:
Master.prototype.__proto__ = EventEmitter.prototype;
( यहां स्रोत )
क्या कोई मुझे एक उदाहरण के साथ समझा सकता है, यह इतना सामान्य पैटर्न क्यों है और जब यह आसान है?
__proto__
एक विरोधी पैटर्न है, कृपया उपयोग करेंMaster.prototype = Object.create(EventEmitter.prototype);
util.inherits(Master, EventEmitter);
जवाबों:
जैसा कि उस कोड के ऊपर दी गई टिप्पणी कहती है, यह Master
विरासत से बना देगा EventEmitter.prototype
, इसलिए आप उस 'वर्ग' के उदाहरणों का उपयोग कर सकते हैं और घटनाओं को सुन सकते हैं।
उदाहरण के लिए आप अब कर सकते हैं:
masterInstance = new Master();
masterInstance.on('an_event', function () {
console.log('an event has happened');
});
// trigger the event
masterInstance.emit('an_event');
अपडेट : जैसा कि कई उपयोगकर्ताओं ने बताया, नोड में ऐसा करने का 'मानक' तरीका 'use.inherits' का उपयोग करना होगा:
var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);
दूसरा अद्यतन : हम पर ES6 कक्षाओं के साथ, EventEmitter
अब कक्षा का विस्तार करने की सिफारिश की गई है :
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
- मैं हमेशा भूल जाता हूं। यहां डॉक्स का लिंक किसी और के मामले में भी है: किसी को भी इसकी आवश्यकता है: nodejs.org/api/events.html#events_class_events_eventemitter )
MasterInstance
करना है, इसलिए होना चाहिए masterInstance
।
Master.prototype = EventEmitter.prototype;
। सुपरर्स की जरूरत नहीं। आप ES6 एक्सटेंड्स का उपयोग भी कर सकते हैं (और यह util.inherits
इस तरह Node.js डॉक्स में प्रोत्साहित किया गया है ) class Master extends EventEmitter
- आप शास्त्रीय प्राप्त करते हैं super()
, लेकिन कुछ भी इंजेक्ट किए बिना Master
।
नोड डॉक अब अपने स्वयं के ईवेंट को उत्सर्जित करने के लिए वर्ग उत्तराधिकार का उपयोग करने की सलाह देते हैं :
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');
नोट: यदि आप किसी constructor()
फ़ंक्शन को परिभाषित करते हैं MyEmitter
, तो आपको super()
अभिभावक वर्ग के निर्माता को यह सुनिश्चित करने के लिए कॉल करना चाहिए , जब तक कि आपके पास कोई अच्छा कारण न हो।
super()
की आवश्यकता नहीं है , जब तक आपको एक निर्माता की आवश्यकता / परिभाषित नहीं होती है, इसलिए ब्रीडली का मूल उत्तर (EDIT इतिहास देखें) पूरी तरह से सही था। इस मामले में आप उत्तर में इस एक ही उदाहरण को कॉपी और पेस्ट कर सकते हैं, कंस्ट्रक्टर को पूरी तरह से हटा सकते हैं और यह उसी तरह काम करेगा। यह पूरी तरह से वैध सिंटैक्स है।
किसी अन्य जावास्क्रिप्ट ऑब्जेक्ट से विरासत में प्राप्त करने के लिए, विशेष रूप से Node.js का EventEmitter लेकिन सामान्य रूप से वास्तव में कोई भी वस्तु, आपको दो काम करने की आवश्यकता है:
[[proto]]
आपके निर्माता से बनाई गई वस्तुओं के लिए उपयोग किया जाएगा ; इस मामले में कि आप किसी अन्य वस्तु से विरासत में प्राप्त कर रहे हैं, आप संभवतः अपने प्रोटोटाइप के रूप में दूसरी वस्तु के उदाहरण का उपयोग करना चाहते हैं।यह जावास्क्रिप्ट में अधिक जटिल है क्योंकि यह अन्य भाषाओं में लग सकता है क्योंकि
Node.js के EventEmitter के विशिष्ट मामले के लिए, यहाँ क्या काम किया गया है:
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);
संभावित तंतु:
util.inherits
, लेकिन EventEmitter
अपनी कक्षा के उदाहरणों के लिए सुपर कंस्ट्रक्टर ( ) को कॉल न करें , तो वे ठीक से प्रारंभ नहीं किए जाएंगे।new EventEmitter
) Master.prototype
इसके बजाय उप-निर्माण निर्माता Master
को सुपर कंस्ट्रक्टर कहें EventEmitter
; सुपरक्लास कंस्ट्रक्टर के व्यवहार पर निर्भर करता है कि ऐसा लग सकता है कि यह थोड़ी देर के लिए ठीक काम कर रहा है, लेकिन यह एक ही चीज नहीं है (और EventEmitter के लिए काम नहीं करेगा)।Master.prototype = EventEmitter.prototype
ऑब्जेक्ट के माध्यम से ऑब्जेक्ट की अतिरिक्त परत जोड़ने के बजाय सीधे सुपर प्रोटोटाइप ( ) का उपयोग करने का प्रयास कर सकते हैं ; ऐसा लगता है कि यह तब तक ठीक काम कर सकता है जब तक कि कोई आपकी वस्तु Master
को बंद नहीं कर देता है EventEmitter
और अनजाने में भी बंदर और उसके अन्य सभी वंशज हो जाते हैं। प्रत्येक "क्लास" का अपना प्रोटोटाइप होना चाहिए।फिर से: EventEmitter (या वास्तव में किसी भी मौजूदा वस्तु "वर्ग" से विरासत में), आप एक कंस्ट्रक्टर को परिभाषित करना चाहते हैं जो सुपर कंस्ट्रक्टर को चेन प्रदान करता है और एक प्रोटोटाइप प्रदान करता है जो सुपर प्रोटोटाइप से प्राप्त होता है।
यह कैसे जावास्क्रिप्ट में प्रोटोटाइप (प्रोटोटाइप) है। से MDN :
ऑब्जेक्ट के प्रोटोटाइप का संदर्भ देता है, जो एक ऑब्जेक्ट या शून्य हो सकता है (जिसका आमतौर पर मतलब है ऑब्जेक्ट ऑब्जेक्ट.प्रोटोटाइप, जिसमें कोई प्रोटोटाइप नहीं है)। इसका उपयोग कभी-कभी प्रोटोटाइप-इनहेरिटेंस बेस्ड प्रॉपर्टी लुकअप को लागू करने के लिए किया जाता है।
यह भी काम करता है:
var Emitter = function(obj) {
this.obj = obj;
}
// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
जावास्क्रिप्ट को समझना OOP सबसे अच्छे लेखों में से एक है जिसे मैंने हाल ही में ECMAScript 5 में OOP पर पढ़ा है।
Y.prototype = new X();
एक विरोधी पैटर्न है, कृपया उपयोग करेंY.prototype = Object.create(X.prototype);
new X()
का एक उदाहरण तात्कालिकता X.prototype
और उस X
पर आह्वान द्वारा इसे इनिशियलाइज़ करता है । Object.create(X.prototype)
बस एक उदाहरण है। आप Emitter.prototype
आरंभीकृत नहीं करना चाहते हैं। मुझे एक अच्छा लेख नहीं मिला जो यह बताता हो।
मुझे लगा कि यह दृष्टिकोण http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm से बहुत साफ था:
function EventedObject(){
// Super constructor
EventEmitter.call( this );
return( this );
}
डगलस क्रॉकफोर्ड के पास कुछ दिलचस्प विरासत पैटर्न भी हैं: http://www.crockford.com/javascript/inheritance.html
मुझे लगता है कि जावास्क्रिप्ट और Node.js. में विरासत अक्सर कम होती है लेकिन एक ऐप लिखने में जहां विरासत में स्केलेबिलिटी को प्रभावित किया जा सकता है, मैं प्रदर्शन को बनाए रखने के खिलाफ तौला जाएगा। अन्यथा, मैं केवल अपने निर्णय को आधार बनाऊंगा, जिस पर पैटर्न बेहतर समग्र डिजाइन की ओर ले जाते हैं, अधिक रखरखाव योग्य होते हैं, और कम त्रुटि-प्रवण होते हैं।
एक तुलना करने के लिए Google Chrome (V8) का उपयोग करके jsPerf में अलग-अलग पैटर्न का परीक्षण करें। V8 जावास्क्रिप्ट इंजन है जिसका उपयोग Node.js और Chrome दोनों द्वारा किया जाता है।
यहाँ कुछ jsPerfs आरंभ करने के लिए हैं:
http://jsperf.com/prototypes-vs-functions/4
emit
और on
के रूप में अपरिभाषित आ रहे हैं।
Wprl की प्रतिक्रिया को जोड़ने के लिए। उन्होंने "प्रोटोटाइप" भाग को याद किया:
function EventedObject(){
// Super constructor
EventEmitter.call(this);
return this;
}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part
util.inherits
चूंकि बहुत सारे स्मार्ट लोग आपके लिए उन विकल्पों को रखेंगे।