最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How do you do custom events on a JavaScript (ES6) class? - Stack Overflow

programmeradmin1浏览0评论

When I search for custom events on JavaScript classes, I get a lot of old or inplete results. MDN shows a custom event off of a dom element. Stackoverflow's top result is almost ten years old and it uses the pre-ES6 syntax.

Is there a way of doing something like:

class Dog
{
  constructor(name)
  {
    this.name = name;
  }
  
  //something to expose bark event
  
}

const buddy = new Dog('buddy');
buddy.addEventListener("bark", function(e) {
  console.log(`${this.name} barked!`);
});

When I search for custom events on JavaScript classes, I get a lot of old or inplete results. MDN shows a custom event off of a dom element. Stackoverflow's top result is almost ten years old and it uses the pre-ES6 syntax.

Is there a way of doing something like:

class Dog
{
  constructor(name)
  {
    this.name = name;
  }
  
  //something to expose bark event
  
}

const buddy = new Dog('buddy');
buddy.addEventListener("bark", function(e) {
  console.log(`${this.name} barked!`);
});

Share Improve this question asked Jul 28, 2021 at 17:25 dholmdholm 231 silver badge3 bronze badges 5
  • 1 unsure how a class has event listeners. Not sure what you are expecting to happen. You probably just want to implement methods. – epascarello Commented Jul 28, 2021 at 17:27
  • You can extend EventEmitter which can provide you the event handling functionalities. Check more nodejs/api/events.html#events_class_eventemitter – Sajeeb Ahamed Commented Jul 28, 2021 at 17:33
  • 1 what do you mean by custom events? why not simply add a method to your class and call it when you want to trigger it? – Rod911 Commented Jul 28, 2021 at 17:41
  • because I want to allow clients to listen in on when the bark event happens. – dholm Commented Jul 28, 2021 at 17:56
  • JavaScript is not or C#. It doesn't define events in object interfaces. – Bergi Commented Jul 28, 2021 at 20:29
Add a ment  | 

4 Answers 4

Reset to default 4

But in your snippet, you wanted to have dog.bark(), in that case see below

class Dog {
  addEventListener(method,callback) {
     this[method] = callback;
  }

  removeEventListener (method) {
      delete this[method];
   }
}

The above will work as

const dog = new Dog();

dog.addEventListener('bark', ()=>console.log("bow"));
dog.bark() // logs => bow

dog.addEventListener('somethingsomething', ()=>{ /*do something*/ })

dog.removeListener('bark');

We can implement tiny class as EventEmitter pattern

class Dog {
   constructor() {
      this.listeners = {};
   }

   emit(method, payload = null) {
      const callback = this.listeners[method];
      if(typeof callback === 'function'){
          callback(payload);
      }
  }

  addEventListener(method,callback) {
     this.listeners[method] = callback;
  }

  removeEventListener (method) {
      delete this.listeners[method];
   }
}

And we can use this class like this

const dog = new Dog();

dog.addEventListener('bark',(customSound)=>console.log(customSound || "Bow Bow"));

dog.addEventListener('eat', ()=>console.log("eating yum yum") );

dog.emit('bark') // logs => Bow Bow
dog.emit('bark', 'i can talk humans') // logs => i can talk humans
dog.emit('eat');

dog.removeEventListener('bark');

Note: it's raw implementation, not production ready code. Thanks.

There are no events with a class. You can implement something that registers functions and you can call them when the method is triggered. Basic idea:

class Animal {
  #registered = {};
  
  constructor(name)
  {
    this.name = name;
  }  
  
  addEventListener(name, callback) {
    if (!this.#registered[name]) this.#registered[name] = [];
    this.#registered[name].push(callback);
  }
  triggerEvent(name, args) {
     this.#registered[name]?.forEach(fnc => fnc.apply(this, args));
  }
}


class Dog extends Animal
{
  constructor(name)
  {
    super(name);
  }
  
  bark(){
    console.log('bark was called');
    this.triggerEvent('bark');
  }

  eat(what){
    console.log('eat was called', what);
    this.triggerEvent('eat', [what]);
  }

}

const buddy = new Dog('buddy');
buddy.addEventListener("bark", function() {
  console.log(`${this.name} barked!`);
});
buddy.addEventListener("eat", function(item) {
  console.log(`${this.name} ate a ${item}!`);
});
buddy.bark();
buddy.eat('bone');

Extend EventTarget class to get all event functions:

https://developer.mozilla/en-US/docs/Web/API/EventTarget/EventTarget

@varaprasadh approach helped me get started, but lacked accumulating multiple events. Modified to also allow remove listener that functions similar to on DOM events to get rid of one based on callback.

class Dog {
  constructor() {
    this.listeners = {};
  }

  emit(method, payload = null) {
    if (this.listeners.hasOwnProperty(method)) {
      const callbacks = this.listeners[method];
      for (let [key, callback] of Object.entries(callbacks)) {
        if (typeof callback === 'function') {
          callback(payload);
        }
      }
    }
  }

  addEventListener(method, callback) {
    if (!this.listeners.hasOwnProperty(method)) {
      this.listeners[method] = {}
    }
    this.listeners[method][callback] = callback;
  }

  removeEventListener(method, callback) {
    if (this.listeners.hasOwnProperty(method)) {
      delete this.listeners[method][callback];
    }
  }
}

发布评论

评论列表(0)

  1. 暂无评论