SOURCE

console 命令行工具 X clear

                    
>
console
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button class="btn">通知执行</button>

  <script>
    class Sub {
      constructor() {
        // 创建事件池(关键就是这个结构的设计)
        this.pond = {};
        // {
        //   'AAA': [fn1, fn2, ...],
        //   'BBB': [fn1, fn2, ...]
        // }
      }

      on(event, fn) {
        if (!this.pond[event]) this.pond[event] = []
        if (!this.pond[event].includes(fn)) this.pond[event].push(fn)
      }
      off(event, fn) {
        if (!fn) { // 如果没有指定 fn,则直接把当前传进来的事件类型event 移除
          delete this.pond[event]
          return;
        }
        if (!this.pond[event]) return;
        this.pond[event] = this.pond[event].filter(item => item !== fn)
      }
      emit(event, ...params) {
        if (!this.pond[event]) return;
        this.pond[event].forEach(fn => fn(...params))
      }
    }

    let fn1 = (x, y) => console.log('fn1', x, y);
    let fn2 = () => {
      console.log('fn2')
      sub1.off('AAA', fn1);
      sub1.off('AAA', fn2);
    };
    let fn3 = () => console.log('fn3');
    let fn4 = () => console.log('fn4');
    let fn5 = (x, y) => console.log('fn5', x, y);

    let sub1 = new Sub();
    let sub2 = new Sub();

    sub1.on('AAA', fn1);
    sub1.on('AAA', fn2);
    sub1.on('AAA', fn3);
    sub1.on('AAA', fn4);
    sub1.on('BBB', fn5);

    sub2.on('CCC', fn5);

    // setTimeout(() => {
    //   sub1.emit('AAA', 10, 20);
    // })

    const btn = document.querySelector(".btn");
    btn.addEventListener("click", function () {
      sub1.emit('AAA', 10, 20);
      sub1.emit('BBB', 100, 200);
      sub2.emit('CCC', 1000, 2000);
    })
  </script>
</body>

</html>