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

在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的文档对象模型DOM》;《js 大厦之JavaScript事件》;《细说JavaScript BOM》等,请多多关注。

JavaScript原生实现观察者模式的更多相关文章

  1. jQuery? 回归JavaScript原生API

    如今技术日新月异,各类框架库也是层次不穷.即便当年漫山红遍的JQuery(让开发者write less, do more,So Perfect!!)如今也有被替代的大势.但JS原生API写法依旧:并且 ...

  2. 据说每个大牛、小牛都应该有自己的库——JavaScript原生对象拓展

    在据说每个大牛.小牛都应该有自己的库——框架篇中我扬言要做个小牛,没想到一天没更新,小伙儿伴们就戏谑的问我,油哥是不是要太监了?其实事情是这个样子的,这不是太监的节奏,一是,关于写个自己的库的想法由来 ...

  3. JavaScript原生折叠扩展收缩菜单带缓冲动画

    JavaScript原生折叠扩展收缩菜单带缓冲动画 @落雨 <div id="div_two" style="display: none;"> &l ...

  4. [转] 有趣的JavaScript原生数组函数

    在JavaScript中,可以通过两种方式创建数组,Array构造函数和 [] 便捷方式, 其中后者为首选方法.数组对象继承自Object.prototype,对数组执行typeof操作符返回‘obj ...

  5. JavaScript原生数组函数

    有趣的JavaScript原生数组函数 在JavaScript中,可以通过两种方式创建数组,构造函数和数组直接量, 其中后者为首选方法.数组对象继承自Object.prototype,对数组执行typ ...

  6. JavaScript原生对象拓展

    JavaScript原生对象拓展 在据说每个大牛.小牛都应该有自己的库——框架篇中我扬言要做个小牛,没想到一天没更新,小伙儿伴们就戏谑的问我,油哥是不是要太监了?其实事情是这个样子的,这不是太监的节奏 ...

  7. 使用 javascript 来实现 观察者模式

    以[猫叫.老鼠跑.主人醒]为例子,使用 javascript 来实现 观察者模式 (有在线演示) 2013-06-24 08:35 by 金色海洋(jyk)阳光男孩, 572 阅读, 4 评论, 收藏 ...

  8. JavaScript原生Array常用方法

    JavaScript原生Array常用方法 在入门Vue时, 列表渲染一节中提到数组的变异方法, 其中包括push(), pop(), shift(), unshift(), splice(), so ...

  9. jQuery 事件绑定 和 JavaScript 原生事件绑定

    总结一下:jQuery 事件绑定 和 JavaScript 原生事件绑定 及 区别 jQuery 事件绑定 jQuery 中提供了四种事件监听绑定方式,分别是 bind.live.delegate.o ...

随机推荐

  1. 安装Pygame(Python3.6,windows)

    1. 本机为python3.6的环境 2. 到pygame官网下载对应系统,对应python版本的pygame文件,下载地址:https://pypi.python.org/pypi/Pygame/1 ...

  2. 7E - The sum problem

    Given a sequence 1,2,3,......N, your job is to calculate all the possible sub-sequences that the sum ...

  3. Python内置的服务器的使用

    cd 到某一文件 Python内置的服务器: E:\myObject\office\netObject\new-gcms> python -m SimpleHTTPServer 8888 如果是 ...

  4. Charles抓https请求详细步骤

    1.电脑上安装好Charles 2.电脑上安装证书 (1)点击Help - SSL Proxying - Install Charlse Root Certificate (2)在电脑上找到证书.此时 ...

  5. dotnet 在build restore publish 的时候不显示警告

    dotnet restore -nowarn:msb3202,nu1503,cs1591 dotnet build -nowarn:msb3202,nu1503,cs1591 --no-restore ...

  6. 联想功能 Jquery autocomplete.js输入框联想补全功能

    转载地址:https://www.cnblogs.com/jinzhiming/p/6768402.html

  7. javascript和c#aes加密方法互解

    关键信息如下. javascript function Encrypt() { var key = CryptoJS.enc.Utf8.parse('8080808080808080'); var i ...

  8. AJAX随笔2

    Ajax作用: 是用JavaScript向服务器发送异步请求,然后服务器给出响应,然后以XML格式的文件返回给浏览器端! 异步: 当浏览器向服务器发送请求的时候,不是整个页面刷新,而是局部刷新[局部信 ...

  9. 【ElasticSearch】 elasticsearch-head插件安装

    本章介绍elasticsearch-head插件安装,elasticsearch安装参考:[ElasticSearch] 安装 elasticsearch-head安装和学习可参照官方文档: http ...

  10. 《数学之美》--第一章:文字和语言 vs 数字和信息

    PDF下载 第一章 文字和语言 vs 数字和信息 数字.文字和自然语言一样,都是信息的载体,它们之间原本有着天然的联系.语言和数学的产生都是为了同一个目的-记录和传播信息.但是,直到半个多世纪前香农博 ...