类似观察者设计模式的JS,问题总结
来源:互联网 发布:中文翻译藏文软件下载 编辑:程序博客网 时间:2024/06/01 20:57
熟悉一个老项目的过程中,许多业务功能是在前端完成的,其中有一个技术点就是如何完成主页面与子页面之间的通信,其中很多js看起来很模糊,后来问同事了解到我们这个项目用到了这么一个js文件主要功能如下
/* * 一个类似观察者设计模式 使用的WEB前端发布(publish) 订阅(subscribe) 的小组件 不需要第3方库的依赖 * * 支持像jquery一样的链式调用风格 * *使用ps.pub / ps.publish 发布事件通知 * *使用ps.sub /ps.subscribe 订阅通知 */!function(w){ var ps={}, subs={}, tokencache=1, tokenPre="pubAndSub-"; /** * 广播订阅者 */ ps.publish=ps.pub=function(){ var args=getArgsAsArrays(arguments); if(args.length<=0){ throw new Error('广播事件必须要指定事件类型'); } var event=args[0]; var calls=subs[event]; if(!calls){//不处理没有用户订阅的事件 return; } var ctx = { event: event, args:args.splice(1)}, len=calls.length; for(var i=0;i<len;i++){ ctx.token=calls[i].token; calls[i].callback.apply(ctx,ctx.args); } return this; } /** * 订阅 */ ps.subscribe=ps.sub=function(event,call){ var a=subs[event]=subs[event]||[], instanceToken=tokenPre+tokencache++; a.push({ token:instanceToken, callback:call }); return instanceToken; } //////////////////////util /** * 获取参数列表 转换为[] */ function getArgsAsArrays(arg){ return Array.prototype.slice.call(arg); } w.ps=ps;}(window);
需要先subscribe,后publish,我们做一个小演示
var person = { name: "ning", sayHi: function() { console.log("person sub......"); } };var msg = ps.sub(person,person.sayHi);ps.pub(person);
我们看看调用sub的代码
ps.subscribe=ps.sub=function(event,call){ var a=subs[event]=subs[event]||[], instanceToken=tokenPre+tokencache++; a.push({ token:instanceToken, callback:call }); return instanceToken; }
在整个JS中先定义了subs这个对象,当我们调用ps.sub的时候,为subs添加了一个event属性,值为[],一个空数组,并将这个空数组的引用给了a,instanceToken只是调用subs时返回的信息,暂且忽略,接着我们,为这个空数组传入了对象,subs这个对象就变成了:
{ Object: [{callback:ƒ (),token:"pubAndSub-1" }]}
其中这个Object就是person对象,ƒ ()就是sayHi那个函数,那么在调用pub的时候做了什么呢
ps.publish=ps.pub=function(){ var args=getArgsAsArrays(arguments); if(args.length<=0){ throw new Error('广播事件必须要指定事件类型'); } var event=args[0]; var calls=subs[event]; if(!calls){//不处理没有用户订阅的事件 return; } var ctx = { event: event, args:args.splice(1)}, len=calls.length; for(var i=0;i<len;i++){ ctx.token=calls[i].token; calls[i].callback.apply(ctx,ctx.args); } return this; }
getArgsAsArrays是将arguments对象转成数组,在ps.pub(person)时,args就是一个数组,只包含person对象这一个值。var event=args[0]; //这一行取出数组第一个元素,即person对象var calls=subs[event]; //拿到这个对象的所有回调函数组成的数组var ctx = { event: event, args:args.splice(1)} //其中这个对象中的event就是我们的person对象,args.splice(1)则删除了第一个元素,只留下了需要传的参数,在我们这次调用中,只留下一个空数组,因为不需传参。在for循环中对所有回调函数,以ctx这个对象为作用域,传入args参数,执行函数。于是在控制台中看到person sub......但是如果我们将person中的sayHi改为如下代码时
var person = { name: "ning", sayName: function() { console.log(this.name); } };var msg = ps.sub(person,person.sayName);ps.pub(person); //undefinedperson.sayName(); //ning
这就牵扯到作用域的问题,关键字为apply(),this
当person.sayName()的时候,this代表的是person这个作用域,所欲this.name即ning
但是当使用观察者模式时,调用sayName的代码变为了如下代码
calls[i].callback.apply(ctx,ctx.args);
apply函数的作用是改变函数的作用域,此时调用sayName()的作用域为ctx,ctx中没有name属性,自然就是undefined,如果想要输出名字,则需要将sayName中的代码改为
console.log(this.event.name);//ning
其中的this.event就是ctx对象中的event属性,本次调用中即为person对象
阅读全文
0 0
- 类似观察者设计模式的JS,问题总结
- 设计模式-观察者模式的另类总结
- js设计模式-观察者模式
- js设计模式-----观察者模式
- JS设计模式-观察者模式
- 观察者模式的总结
- js 设计模式学习--观察者模式
- 【js设计模式笔记---观察者模式】
- JS设计模式——观察者模式
- JS设计模式之观察者模式
- 【js设计模式笔记---观察者模式】
- JS设计模式八:观察者模式
- JS-设计模式之观察者模式
- 项目中的流程及类似业务的设计模式总结
- 设计模式总结之观察者模式
- 设计模式总结—观察者模式
- 设计模式系列总结之观察者模式
- 设计模式总结之观察者模式
- 负载均衡进阶:SLB常见问题解决方法
- CSS3 Transition
- 父类引用子类对象
- 第七周项目一 顺序环形队列算法库的建立及测试
- 欢迎使用CSDN-markdown编辑器1
- 类似观察者设计模式的JS,问题总结
- Mysql-select+update并发更新问题
- SpringBoot自定义个性化的banner
- 二分图的最大匹配模板
- Base64 编解码 工具类
- 最近点对算法分析Closest Pair of Points
- IDEA Spring + websocket + tomcat项目搭建及打包部署
- RecyclerView下拉刷新上拉加载
- mvc和mvvm的区别