前端常用技术点

发布-订阅模式简述

2019-09-30  本文已影响0人  赵小空

简介:

发布-订阅模式可以取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口。发布-订阅模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响它们之间相互通信。当有新的订阅者出现时,发布者的代码不需要任何修改;同样发布者需要改变时,也不会影响到之前的订阅者。只要之前约定的事件名没有变化,就可以自由地改变它们。

简单实现:

class Observer {
    constructor() {
        this.subscribers = {}
    }
    on(type, fn) {
        if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) {
          this.subscribers[type] = [];
        }
        this.subscribers[type].push(fn);
    }
    once(type,fn){
        let cb=(v)=>{
            fn(v);
            this.off(type,cb)
        }
        this.on(type,cb)
    }
    off(type, fn,isall=false) {
        let listeners = this.subscribers[type];
        if (!listeners || !listeners.length) return;
        isall?this.subscribers[type]=[]:this.subscribers[type] = listeners.filter(v => v !== fn );
    }
    emit(type, ...args) {
        let listeners = this.subscribers[type];
        if (!listeners || !listeners.length) return;
        listeners.forEach(fn => fn(...args));        
    }
}

let ob = new Observer();

let click1=function (val){ console.log('这是click1事件=>',val)}
let click2=function (val){ console.log('这是click2事件=>',val)}
ob.on('click', click1);
ob.on('click', click2);
// 每个示例运行单独注释掉即可
// 示例1: 一个事件绑定多个函数
ob.emit('click', '我点击了哦');
// 示例2: 关掉后绑定click1的不会执行 但是绑定click2的可以执行
//如removeEventListener 一样 匿名函数此种写法无法解除
// ob.off('click',click1) 
// ob.emit('click', '我点击了哦');

// 示例3:解除事件绑定的所有函数
// ob.off('click',click1,true)
// ob.emit('click', '我点击了哦');
// 只执行一次的函数
// let fitF=(v)=>{console.log('我执行了fit',v)}
// ob.once('fit',fitF)

// ob.emit('fit','我执行了')
// // 下面2不会执行
// ob.emit('fit','我执行2')

为什么要使用Object.prototype.hasOwnProperty

因为js没有将hasOwnProperty作为一个敏感词,所以我们很有可能将对象的一个属性命名为hasOwnProperty,这样一来就无法再使用对象原型的 hasOwnProperty 方法来判断属性是否是来自原型链。

var foo = {    
hasOwnProperty: function() {        return false;    },    
bar: 'Here be dragons'
}; 
foo.hasOwnProperty('bar'); // 始终返回 false

不能使用 该对象.hasOwnProperty 这种方法,怎么来解决这个问题呢?我们需要使用原型链上真正的 hasOwnProperty 方法

({}).hasOwnProperty.call(foo, 'bar'); // true
// 或者:
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
上一篇 下一篇

猜你喜欢

热点阅读