Узел.js-наследование от EventEmitter



Я вижу этот шаблон в довольно многих узлах.библиотеки js:



Master.prototype.__proto__ = EventEmitter.prototype;


(источник здесь)



может кто-нибудь объяснить мне на примере, почему это такой распространенный шаблон и когда это удобно?

589   6  

6 ответов:

как говорится в комментарии выше этого кода, это сделает Master наследовать от EventEmitter.prototype, Так что вы можете использовать экземпляры этого класса для передачи и прослушивания событий.

например, теперь вы можете сделать:

masterInstance = new Master();

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

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

обновление: как указывали многие пользователи, "стандартный" способ сделать это в узле будет использовать' util.наследует':

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

наследование класса стиля ES 6

они приходят прямо из документов, но я подумал, что было бы неплохо добавить их к этому популярному вопросу для тех, кто ищет.

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');

Я хочу git thank кто бы это ни добавил. Излучатель Событие.

Примечание: документация не вызывает super() в конструкторе, который вызовет this чтобы быть неопределенным. Смотрите это вопрос.

для наследования от другого объекта Javascript, Node.JS EventEmitter в частности, но на самом деле любой объект в целом, вам нужно сделать две вещи:

  • предоставьте конструктор для вашего объекта, который полностью инициализирует объект; в случае, если вы наследуете от какого-либо другого объекта, вы, вероятно, захотите делегировать часть этой работы инициализации суперконструктору.
  • предоставить прототип объекта, который будет использоваться в качестве [[proto]] для объекты, созданные из конструктора; в случае, если вы наследуете от какого-либо другого объекта, вы, вероятно, хотите использовать экземпляр другого объекта в качестве прототипа.

это сложнее в Javascript, чем может показаться на других языках, потому что

  • Javascript разделяет поведение объекта на" конструктор "и"прототип". Эти понятия предназначены для использования вместе, но могут использоваться отдельно.
  • Javascript - это очень податливый язык, и люди используют его по-разному, и нет единого истинного определения того, что означает "наследование".
  • во многих случаях вам может сойти с рук выполнение подмножества того, что правильно, и вы найдете множество примеров для подражания (включая некоторые другие ответы на этот вопрос SO), которые, похоже, отлично работают для вашего случая.

для конкретного случая узел.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);

возможно слабости:

  • если вы используете set прототип для вашего подкласса (Master.прототип), с использованием или без использования util.inherits, но не вызывайте супер конструктор (EventEmitter) для экземпляров вашего класса они не будут правильно инициализированы.
  • если вы вызываете супер конструктор, но не устанавливаете прототип, методы EventEmitter не будут работать на вашем объекте
  • вы можете попробовать использовать инициализированный экземпляр суперкласса (new EventEmitter) как Master.prototype вместо имея конструктор подкласса Master звонок супер конструктор EventEmitter; в зависимости от поведения конструктора суперкласса, который может показаться, что он работает нормально некоторое время, но это не одно и то же (и не будет работать для EventEmitter).
  • вы можете попробовать использовать супер прототип напрямую (Master.prototype = EventEmitter.prototype) вместо добавления дополнительного слоя объекта через объект.создать; это может показаться, что он работает нормально, пока кто-то обезьяны не заберет ваш объект Master и по неосторожности тоже обезьянкаEventEmitter и все остальные его потомки. Каждый "класс" должен иметь свой собственный прототип.

опять же: чтобы наследовать от EventEmitter (или действительно любого существующего объекта "class"), вы хотите определить конструктор, который связывается с супер-конструктором и предоставляет прототип, который является производным от супер-прототипа.

Это как прототипический (прототипный?) наследование выполняется в JavaScript. От MDN:

относится к прототипу объекта, который может быть объектом или null (что обычно означает, что объект является объектом.прототип, который не имеет прототип.) Он иногда используется для реализации прототипа-наследования поиск свойств на основе.

Это тоже работает:

var Emitter = function(obj) {
    this.obj = obj;
}

// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);

понимание JavaScript ООП - один из лучших статей, которые я читал в последнее время на ООП в ECMAScript 5.

Я думал, что этот подход от 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

Я считаю, что наследование реже требуется в JavaScript и Node.js. Но при написании приложения, где наследование может повлиять на масштабируемость, я бы рассмотрите производительность, взвешенную против ремонтопригодности. В противном случае я бы только основывал свое решение на том, какие шаблоны приводят к лучшим общим проектам, более ремонтопригодны и менее подвержены ошибкам.

Проверьте различные шаблоны в jsPerf, используя Google Chrome (V8), чтобы получить грубое сравнение. V8-это движок JavaScript, используемый обоими узлами.js и хром.

вот некоторые jsPerfs, чтобы получить вас начал:

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

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

http://jsperf.com/inheritance-perf

чтобы добавить к ответу wprl. Он пропустил часть "прототипа":

function EventedObject(){

   // Super constructor
   EventEmitter.call(this);

   return this;

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

Comments

    Ничего не найдено.