面试官 : 手写发布订阅模式(subscribe)

subscribe.js 文件

let _subscribe = (function () {
  //=> Sub 发布订阅类
  class Sub {
    constructor() {
      //=>创建一个事件池,用来存储后期需要执行的方法
      this.$pond = [];
    }
    //=>向事件池追加方法;
    add(func) {
      //=>如果传递进来的不是方法,我们不做任何处理
      if (typeof func !== 'function') return;
      //=>把传递进来的方法,存储到事件池中

      //=> 判断事件池中是否有该方法 
      let flag = this.$pond.some(item => item === func);
      
      !flag ? this.$pond.push(func) : null;
    }
    //=> 从事件池中移除方法
    remove(func) {
      if (typeof func !== 'function') return;

      let $pond = this.$pond
      for(let i = 0; i < $pond.length; i++){
        let item = $pond[i];
        if(item === func){
          //移除(顺序不变的情况下基本上只能用splice)但是不能这样写,这会导致数组坍塌问题,我们移除不能真移除,只能把当前项赋值为null
          // $pond.splice(i,1);
          $pond[i] = null;
          break;
        }
      }
    //=>通知事件池中的方法,按照顺序依次执行
    fire(...args) {
      let $pond = this.$pond;
      for (let i = 0; i < $pond.length; i++) {
        let item = $pond[i];
        if(typeof item !== 'function'){
          //此时在删除
          $pond.splice(i,1);
          i--;
          continue;
        }
        item.call(this, ...args);
      }
    }
  }
  //暴露给外面使用
  return function subscribe() {
    return new Sub();
  }
})();

如何使用:

<body>
  <button class="submit">点击</button>
  <script src="subscribe.js"></script>
  <script>
    let $pond = _subscribe();

    document.querySelector('.submit').onclick = function (ev) {
      $pond.fire([1, 2, 3]);
    }

    let fn1 = function () {
      console.log(1)
    }
   
    let fn2 = function () {
      console.log(2)
      $pond.remove(fn1)
    }
    
    let fn3 = function () {
      console.log(3)
    }
    let fn4 = function (ev) {
      console.log(4,ev)
    }

    $pond.add(fn1)
    $pond.add(fn2)
    $pond.add(fn3)
    $pond.add(fn4)

  </script>
</body>

点击两次后的效果:
在这里插入图片描述

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值