JavaScript原生实现观察者模式的示例


Posted in Javascript onDecember 15, 2017

观察者模式又叫做发布订阅模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察着对象。 它是由两类对象组成,主题和观察者,主题负责发布事件,同时观察者通过订阅这些事件来观察该主体,发布者和订阅者是完全解耦的,彼此不知道对方的存在,两者仅仅共享一个自定义事件的名称。

在Nodejs中通过EventEmitter实现了原生的对于这一模式的支持。

在JavaScript中事件监听机制就可以理解为一种观察者模式。通过onclick进行事件绑定,然后通过交互行为进行触发或者事件主动触发。

下面给出一个JS自定义的PubSub,仔细阅读下面这段代码有助于你理解观察者模式。

一、定义观察者类Pubsub

/* Pubsub */
 function Pubsub(){
  //存放事件和对应的处理方法
 this.handles = {};
 }

二、实现事件订阅on

//传入事件类型type和事件处理handle
 on: function (type, handle) {
  if(!this.handles[type]){
   this.handles[type] = [];
  }
  this.handles[type].push(handle);
 }

三、实现事件发布emit

emit: function () {
  //通过传入参数获取事件类型
 var type = Array.prototype.shift.call(arguments);
  if(!this.handles[type]){
   return false;
  }
 for (var i = 0; i < this.handles[type].length; i++) {
   var handle = this.handles[type][i];
   //执行事件
  handle.apply(this, arguments);
  }
 }

需要说明的是Array.prototype.shift.call(arguments)这句代码,arguments对象是function的内置对象,可以获取到调用该方法时传入的实参数组。

shift方法取出数组中的第一个参数,就是type类型。

四、实现事件取消订阅off

off: function (type, handle) {
  handles = this.handles[type];
  if(handles){
   if(!handle){
    handles.length = 0;//清空数组
  }else{
    for (var i = 0; i < handles.length; i++) {
     var _handle = handles[i];
     if(_handle === handle){
      handles.splice(i,1);
     }
    }
   }
  }
 }

完整代码:

/* Pubsub */
 function Pubsub(){
  //存放事件和对应的处理方法
 this.handles = {};
 }
 Pubsub.prototype={
  //传入事件类型type和事件处理handle
  on: function (type, handle) {
   if(!this.handles[type]){
    this.handles[type] = [];
   }
   this.handles[type].push(handle);
  },
  emit: function () {
   //通过传入参数获取事件类型
  var type = Array.prototype.shift.call(arguments);
   if(!this.handles[type]){
    return false;
   }
 for (var i = 0; i < this.handles[type].length; i++) {
    var handle = this.handles[type][i];
    //执行事件
   handle.apply(this, arguments);
   }
  },
  off: function (type, handle) {
   handles = this.handles[type];
   if(handles){
    if(!handle){
     handles.length = 0;//清空数组
   }else{
 for (var i = 0; i < handles.length; i++) {
      var _handle = handles[i];
      if(_handle === handle){
       handles.splice(i,1);
      }
     }
    }
   }
  }
 }

五、测试

var p1 = new Pubsub();
 p1.on('mm', function (name) {
 console.log('mm: '+ name);
 });
 p1.emit('mm','哈哈哈哈');
console.log('===============');
 var p2 = new Pubsub();
 var fn = function (name) {
 console.log('mm2: '+ name);
 };
 var fn2 = function (name) {
 console.log('mm222: '+ name);
 };
 p2.on('mm2', fn);
 p2.on('mm2', fn2);
 p2.emit('mm2','哈2哈2哈2哈2');
 console.log('-------------');
p2.off('mm2', fn);
 p2.emit('mm2','哈2哈2哈2哈2');
 console.log('-------------');
p2.off('mm2');
 p2.emit('mm2','哈2哈2哈2哈2');
 console.log('-------------');

JavaScript原生实现观察者模式的示例

以上这篇JavaScript原生实现观察者模式的示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js AspxButton的客户端操作
Jun 26 Javascript
25个非常棒的jQuery滑块插件和教程小结
Sep 02 Javascript
关于JS判断图片是否加载完成且获取图片宽度的方法
Apr 09 Javascript
Web跨浏览器进程通信(Web跨域)
Apr 17 Javascript
JS 去除Array中的null值示例代码
Nov 20 Javascript
JavaScript中的console.log()函数详细介绍
Dec 29 Javascript
Bootstrap树形菜单插件TreeView.js使用方法详解
Nov 01 Javascript
jQuery插件扩展操作入门示例
Jan 16 Javascript
React-Native中props具体使用详解
Sep 04 Javascript
seajs实现强制刷新本地缓存的方法分析
Oct 16 Javascript
javascript+jQuery实现360开机时间显示效果
Nov 03 jQuery
three.js欧拉角和四元数的使用方法
Jul 26 Javascript
基于javascript 显式转换与隐式转换(详解)
Dec 15 #Javascript
ReactNative中使用Redux架构总结
Dec 15 #Javascript
Angular中使用MathJax遇到的一些问题
Dec 15 #Javascript
vue实现验证码输入框组件
Dec 14 #Javascript
基于滚动条位置判断的简单实例
Dec 14 #Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
Dec 14 #Javascript
ES6/JavaScript使用技巧分享
Dec 14 #Javascript
You might like
PHP OPCode缓存 APC详细介绍
2010/10/12 PHP
PHP小程序支付功能完整版【基于thinkPHP】
2019/03/26 PHP
laravel 解决多库下的DB::transaction()事务失效问题
2019/10/21 PHP
PHP快速导出百万级数据到CSV或者EXCEL文件
2020/11/27 PHP
IE event.srcElement和FF event.target 功能比较
2010/03/01 Javascript
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
A标签触发onclick事件而不跳转的多种解决方法
2013/06/27 Javascript
jQuery中index()方法用法实例
2014/12/27 Javascript
快速学习jQuery插件 jquery.validate.js表单验证插件使用方法
2015/12/01 Javascript
jQuery的选择器中的通配符[id^='code']或[name^='code']及jquery选择器总结
2015/12/24 Javascript
angularJS Provider、factory、service详解及实例代码
2016/09/21 Javascript
JS button按钮实现submit按钮提交效果
2016/11/01 Javascript
基于vue2.x的电商图片放大镜插件的使用
2018/01/22 Javascript
Vue实现剪切板图片压缩功能
2020/02/04 Javascript
Vue自动构建发布脚本的方法示例
2020/07/24 Javascript
[05:08]2014DOTA2国际邀请赛 Hao专访复仇的胜利很爽
2014/07/15 DOTA
Python读取txt某几列绘图的方法
2018/10/14 Python
基于wxPython的GUI实现输入对话框(2)
2019/02/27 Python
使用Python爬虫库requests发送表单数据和JSON数据
2020/01/25 Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
2020/03/07 Python
python mysql中in参数化说明
2020/06/05 Python
python怎么删除缓存文件
2020/07/19 Python
Python环境配置实现pip加速过程解析
2020/11/27 Python
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
法国二手MacBook销售网站:Okamac
2019/03/18 全球购物
网络安全类面试题
2015/08/01 面试题
公司董事长职责
2013/12/12 职场文书
会计学习心得体会
2014/09/09 职场文书
电子银行业务授权委托书
2014/10/10 职场文书
任长霞观后感
2015/06/16 职场文书
2015年秋学期教研工作总结
2015/10/14 职场文书
vue引入Excel表格插件的方法
2021/04/28 Vue.js
springboot新建项目pom.xml文件第一行报错的解决
2022/01/18 Java/Android
详解Vue中$props、$attrs和$listeners的使用方法
2022/02/18 Vue.js
mysql使用instr达到in(字符串)的效果
2022/04/03 MySQL
MySQL控制流函数(-if ,elseif,else,case...when)
2022/07/07 MySQL