js 订阅者模式(观察者模式) 悠悠 2022-07-15 13:15 213阅读 0赞 原文网址:http://www.cnblogs.com/LuckyWinty/p/5796190.html [附加题] 请实现下面的自定义事件 Event 对象的接口,功能见注释(测试1) 该 Event 对象的接口需要能被其他对象拓展复用(测试2) // 测试1 Event.on('test', function (result) { console.log(result); }); Event.on('test', function () { console.log('test'); }); Event.emit('test', 'hello world'); // 输出 'hello world' 和 'test' // 测试2 var person1 = {}; var person2 = {}; Object.assign(person1, Event); Object.assign(person2, Event); person1.on('call1', function () { console.log('person1'); }); person2.on('call2', function () { console.log('person2'); }); person1.emit('call1'); // 输出 'person1' person1.emit('call2'); // 没有输出 person2.emit('call1'); // 没有输出 person2.emit('call2'); // 输出 'person2' var Event = { // 通过on接口监听事件eventName // 如果事件eventName被触发,则执行callback回调函数 on: function (eventName, callback) { //你的代码 }, // 触发事件 eventName emit: function (eventName) { //你的代码 } }; 上面的这道题就是所谓的js的观察者模式 所谓观察者模式就是一种创建耦合代码的技术。它定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时候,所有依赖于它的对象都将得到通知。由主体和观察者组成,主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。主体并不知道观察者任何事情,观察者知道主体并能注册事件的回调函数。 例子: 假如我们正在开发一个商城网站,网站里有header头部、nav导航、消息列表、购物车等模块。这几个模块的渲染有一个共同的前提条件,就是必须先用ajax异步请求获取用户的登录信息。这是很正常的,比如用户的名字和头像要显示在header模块里,而这两个字段都来自用户登录后返回的信息。这个时候,我们就可以把这几个模块的渲染事件都放到一个数组里面,然后待登录成功之后再遍历这个数组并且调用每一个方法 方法: function EventTarget(){ this.handlers={}; } EventTarget.prototype={ constructor:EventTarget; addHandler:function(type,handler){ if(typeof this.handlers[type]=="undefined"){ this.handlers[type]=[]; } this.handlers[type].push(handler); }, fire:function(event){ if(!event.target){ event.target = this; } if(this.handlers[event.type] instanceof Array){ var handlers=this.handlers[event.type]; for(var i=0,len=handlers.lenth;i<len;i++){ handlers[i](event); } } }, removeHandler: function(type, handler){ if (this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; for (var i=0, len=handlers.length; i < len; i++){ if (handlers[i] === handler){ break; } } handlers.splice(i, 1); } } }; 现在回到题目中的测试一: 利用的是观察者模式: var Event={ handles:{}, on:function(eventtype,callback){ if(!this.handles[eventtype]){ this.handles[eventtype]=[]; } this.handles[eventtype].push(callback); }, emit:function(eventtype){ if(this.handles[arguments[0]]){ for(var i=0;i<this.handles[arguments[0]].length;i++){ this.handles[arguments[0]][i](arguments[1]); } } } }; 题目的测试二: var person1 = {}; var person2 = {}; Object.assign(person1, Event); Object.assign(person2, Event); person1.on('call1', function () { console.log('person1'); }); person2.on('call2', function () { console.log('person2'); }); person1.emit('call1'); // 输出 'person1' person1.emit('call2'); // 没有输出 person2.emit('call1'); // 没有输出 person2.emit('call2'); // 输出 'person2' 大概意思就是为两个不同person注册自定义事件,并且两个person之间是互相独立的。 但是实际结果测试如下: 这个好像是题目要求有点出入呢,或者这才是题目的坑吧! 解释一下,Object.assign(person1, Event); 这个是ES6的新对象方法,用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。 意思是将Event里面的可枚举的对象和方法放到person1里面。 也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。由于进行测试一的时候调用了on方法,所以event里面已经有了handles这个可枚举的属性。然后再分别合并到两个person里面的话,两个person对象里面的handles都只是一个引用。所以就互相影响了。 如果assign方法要实现深克隆则要这样: 问题是,题目已经固定了方式,我们不能修改这个方法。 所以,我们必须将handles这个属性定义为不可枚举的,然后在person调用on方法的时候再分别产生handles这个对象。 也就是说正确的做法应该是: var Event = { // 通过on接口监听事件eventName // 如果事件eventName被触发,则执行callback回调函数 on: function (eventName, callback) { //你的代码 if(!this.handles){ //this.handles={}; Object.defineProperty(this, "handles", { value: {}, enumerable: false, configurable: true, writable: true }) } if(!this.handles[eventName]){ this.handles[eventName]=[]; } this.handles[eventName].push(callback); }, // 触发事件 eventName emit: function (eventName) { //你的代码 if(this.handles[arguments[0]]){ for(var i=0;i<this.handles[arguments[0]].length;i++){ this.handles[arguments[0]][i](arguments[1]); } } } };
相关 观察者模式 vs 发布订阅模式 目录 场景 观察者模式 发布订阅模式 总结 -------------------- 场景 有一回面试,面试官问: 末蓝、/ 2023年10月06日 19:03/ 0 赞/ 30 阅读
相关 JS-观察者模式 如果说,你只能掌握一种设计模式,那必须毫不犹豫的选择观察者模式,也叫发布订阅模式。 es6中promise的实现、vue中双向绑定原理的实现、Node.js中的 EventE 港控/mmm°/ 2023年08月17日 15:26/ 0 赞/ 98 阅读
相关 订阅发布和观察者模式 发布订阅模式 > 把多个方法暂存起来,最后一次触发执行 作用: 解偶 使用场景: 如,多个类或者函数内,可以分散订阅某个操作,最后统一发布。分散的好处就是不 ╰+攻爆jí腚メ/ 2022年08月28日 14:47/ 0 赞/ 222 阅读
相关 观察者模式——出版者与订阅者 在说Java内置的观察者模式之前,我们先来回顾一下大话中这个模式的例子。如下图,前台负责通知那些看股票和看新闻的人,告知他们情况,这些看股票、看新闻的人对此做出反 分手后的思念是犯贱/ 2022年08月12日 10:59/ 0 赞/ 178 阅读
相关 js 订阅者模式(观察者模式) 原文网址:http://www.cnblogs.com/LuckyWinty/p/5796190.html [附加题] 请实现下面的自定义事件 Event 对 悠悠/ 2022年07月15日 13:15/ 0 赞/ 214 阅读
相关 js观察者模式 定义: 观察者模式又叫做发布/订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察着对象。它是由两类对 小鱼儿/ 2022年06月07日 00:09/ 0 赞/ 126 阅读
相关 观察者模式(发布-订阅者模式) 观察者模式定义了一种依赖关系,解决了主体对象和观察者之间功能的耦合,主要应用于大型项目的模块化开发中,解决团队开发中模块之间的通信问题,利用观察者模式还可以实现自定义事件。 素颜马尾好姑娘i/ 2022年05月22日 06:00/ 0 赞/ 236 阅读
相关 javascript 观察者模式 发布订阅模式 观察者模式 观察者模式,每一个观察者对象有两个方法 添加监听`subscribe` 发布事件`publish` 观察者有个`list`存放所有的已经添加监 本是古典 何须时尚/ 2022年04月24日 10:14/ 0 赞/ 230 阅读
相关 发布订阅模式(观察者模式) 设计模式的目的就是使类成为可复用的组件。 在观察者模式中观察者接口只注重被观察者,而被观察者接口只注重观察者,具体是观察者接口实现类中的哪一个并不在意,而被观察者也是如此。这 清疚/ 2021年12月15日 00:27/ 0 赞/ 311 阅读
还没有评论,来说两句吧...