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 相关文章推荐
给Function做的OOP扩展
May 07 Javascript
利用jq让你的div居中的好方法分享
Nov 21 Javascript
JSP中使用JavaScript动态插入删除输入框实现代码
Jun 13 Javascript
javascript使用正则获取url上的某个参数
Sep 04 Javascript
学习JavaScript设计模式(单例模式)
Nov 26 Javascript
详解AngularJS中的http拦截
Feb 09 Javascript
javascript数组遍历的方法实例分析
Sep 13 Javascript
JS 动态加载js文件和css文件 同步/异步的两种简单方式
Sep 23 Javascript
基于MVC方式实现三级联动(JavaScript)
Jan 23 Javascript
bootstarp modal框居中显示的实现代码
Feb 18 Javascript
layer弹出层扩展主题的方法
Sep 11 Javascript
Vue父子传递实例讲解
Feb 14 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
yii上传文件或图片实例
2014/04/01 PHP
PHP实现将多个文件中的内容合并为新文件的方法示例
2017/06/10 PHP
原生JS实现Ajax通过POST方式与PHP进行交互的方法示例
2018/05/12 PHP
PHP一个简单的无需刷新爬虫
2019/01/05 PHP
laravel返回统一格式错误码问题
2019/11/04 PHP
php判断某个方法是否存在函数function_exists (),method_exists()与is_callable()区别与用法解析
2020/04/20 PHP
ext读取两种结构的xml的代码
2008/11/05 Javascript
JavaScript 动态添加表格行 使用模板、标记
2009/10/24 Javascript
JSChart轻量级图形报表工具(内置函数中文参考)
2010/10/11 Javascript
jQuery中nextAll()方法用法实例
2015/01/07 Javascript
一不小心就做错的JS闭包面试题
2015/11/25 Javascript
jQuery Uploadify 上传插件出现Http Error 302 错误的解决办法
2015/12/12 Javascript
jQuery+PHP+MySQL实现无限级联下拉框效果
2016/02/19 Javascript
JavaScript预解析及相关技巧分析
2016/04/21 Javascript
深入理解(function(){... })();
2016/08/16 Javascript
jquery操作checkbox火狐下第二次无法勾选的解决方法
2016/10/10 Javascript
jquery网页日历显示控件calendar3.1使用详解
2016/11/24 Javascript
bootstrapValidator.min.js表单验证插件
2017/02/09 Javascript
Angular 2父子组件数据传递之@Input和@Output详解(下)
2017/07/05 Javascript
基于JavaScript实现图片连播和联级菜单实例代码
2017/07/28 Javascript
Vue.js 实现数据展示全部和收起功能
2018/09/05 Javascript
Vue 实现点击空白处隐藏某节点的三种方式(指令、普通、遮罩)
2019/10/23 Javascript
python实现将文本转换成语音的方法
2015/05/28 Python
Python读csv文件去掉一列后再写入新的文件实例
2017/12/28 Python
英国高档时尚男装购物网站:MR PORTER
2016/08/09 全球购物
英国户外装备和冒险服装零售商:alloutdoor
2018/01/30 全球购物
Banana Republic英国官网:香蕉共和国,GAP集团旗下偏贵族风
2018/04/24 全球购物
美国高级音响品牌:Master&Dynamic
2018/07/05 全球购物
可爱的童装和鞋子:Fabkids
2019/08/16 全球购物
应聘美工求职信
2013/11/07 职场文书
实习单位评语
2014/04/26 职场文书
给下属加薪申请报告
2015/05/15 职场文书
2015年见习期个人工作总结
2015/05/28 职场文书
用position:sticky完美解决小程序吸顶问题的实现方法
2021/04/24 HTML / CSS
数据库之SQL技巧整理案例
2021/07/07 SQL Server
webpack介绍使用配置教程详解webpack介绍和使用
2022/06/25 Javascript