That’s basically what the front-end interview is all about

class EventEmitter {
  constructor(defaultMaxListeners = 50) {
    this.defaultMaxListeners = defaultMaxListeners;
    this.listener = {};
  }

  / / subscribe
  on(eventName, fn) {
    if (!this.listener[eventName]) {
      this.listener[eventName] = [];
    }
    if (this.listener[eventName].length >= this.defaultMaxListeners) {
      throw `${eventName}Overmax monitorThe ${this.defaultMaxListeners}Number limit ';
    }
    this.listener[eventName].push(fn);
  }

  / / cancel
  off(eventName, fn) {
    let callBacks = this.listener[eventName];
    if(! callBacks) {return false;
    }
    if(! fn) { callBacks = []; }else {
      let cb;
      for (let i = 0; i < callBacks.length; i++) {
        cb = callBacks[i];
        if (cb === fn || cb.fn === fn) {
          callBacks.splice(i, 1); i--; }}}}// Listen once
  once(eventName, fn) {
    const on = (. args) = > {
      this.off(eventName, on);
      fn.apply(this. args); };// Unsubscribe
    on.fn = fn;
    this.on(eventName, on);
  }

  / / release
  emit(eventName, ... args) {
    const callBackFn = this.listener[eventName] || [];
    if (callBackFn.length === 0) {
      throw `${eventName}There is no `;
    }
    callBackFn.forEach((fn) = >{ fn(args); }); }}const $event = new EventEmitter();

function fn1(. args) {
  console.log("fn111111". args); }function fn2(. args) {
  console.log("fn2". args); } $event.once("fn1", fn2);

// $event.on("fn1", fn1);
// $event.on("fn1", fn1);
// $event.on("fn1", fn2);

// $event.on("fn1", fn1);
// // event.off("fn1", fn1);
// $event.on("fn2", fn1);
// $event.on("fn3", fn1);
// $event.on("fn4", fn1);

$event.emit("fn1"."Fn1 parameter 2"."Three parameters".4 "parameters");
// $event.emit("fn1", "fn2 fn2");

Copy the code

supplement

The arrow function has several uses with caution.

  • (1) The this object inside the function is the object at which it is defined, not the object at which it is used.
  • (2) Cannot be used as a constructor, that is, cannot use the new command, otherwise an error will be thrown.
  • (3) You can’t use arguments. This object does not exist in the function body. If you do, use the REST argument instead.
  • (4) Yield cannot be used, so arrow functions cannot be used as Generator functions.

The first of these four points is particularly noteworthy. The point of this object is mutable, but in arrow functions, it is fixed.

function test() {
  console.log("test arguments".arguments);
  const fn = (. args) = > {
    console.log("fn arguments".arguments);
    console.log("fn args", args);
  };
  fn("fn");
}

test("test");
Copy the code

The results of

// test arguments [Arguments] { '0': 'test' }
// fn arguments [Arguments] { '0': 'test' }
// fn args [ 'fn' ]
Copy the code