当前位置: 首页 > news >正文

JavaScript 观察者设计模式

观察者模式:观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行。而js中最常见的观察者模式就是事件触发机制。

ES5/ES6实现观察者模式(自定义事件) - 简书

先搭架子

  1. 要有一个对象,存储着它自己的触发函数。而且这个对象的触发函数可能有很多种,比如一个onclick可能触发多个事件,那么handler的属性应该是一个数组,每个数组的值都是一个函数。
handler={type1:[func1,func2...],type2:[func3,func4...],...
}
  1. 现在这个对象的主体部分已经思考好了,现在就是要它‘动起来’,给它添加各种动作。
    一个事件可能有哪些动作呢?
  • add:添加事件某种类型的函数,
  • remove: 移除某种类型的函数,
  • fire:触发某种类型的函数,
  • once:触发某种类型的函数,然后移除掉这个函数
  1. 现在,自定义事件的架子已经搭建好了
eventOb={//函数储存handler:{type1:[func1,func2...],type2:[func2,func4...],...},//主要事件add:function(){},remove:function(){},fire:function(){},once:function(){},
}

add

添加一个事件监听,首先传入参数应该是 事件类型type,和触发函数 func,传入的时候检测有没有这个函数,有了就不重复添加。

add:function (type,func) {//检测type是否存在if(eventOb.handleFunc[type]){//检测事件是否存在,不存在则添加if(eventOb.handleFunc[type].indexOf(func)===-1){eventOb.handleFunc[type].push(func);}}else{eventOb.handleFunc[type]=[func];}
},

remove

remove有一个潜在的需求,就是如果你的事件不存在,它应该会报错。而这里不会报错,index在func不存在的时候是-1;这时候要报错。

remove:function (type,func) {try{let target = eventOb.handleFunc[type];let index = target.indexOf(func);if(index===-1) throw error;target.splice(index,1);}catch (e){console.error('别老想搞什么飞机,删除我有的东西!');}
},

fire

触发一个点击事件肯定是要触发它全部的函数,这里也是一样,所以只需要传入type,然后事件可能不存在,像上面一样处理。

fire:function (type,func) {try{let target = eventOb.handleFunc[type];let count = target.length;for (var i = 0; i < count; i++) {//加()使立即执行target[i]();}    }catch (e){console.error('别老想搞什么飞机,触发我有的东西!');}
},

once

fire,然后remove?

但会有问题,我只想触发并且删除某个事件怎么办,fire一下就全触发了呀。
所以fire的问题就显现出来了。我们还是要给它一个func,但是可选。

fire:function (type,func) {try{let target = eventOb.handleFunc[type];if(arguments.length===1) {//不传func则全部触发let count = target.length;for (var i = 0; i < count; i++) {target[i]();}}else{//传func则触发funclet index=target.indexOf(func);if(index===-1)throw error;func();}//need some code}catch (e){console.error('别老想搞什么飞机,触发我有的东西!');//need some code}
},

完整代码

class eventObs {constructor(){this.handleFunc={}}add(type,func){if(this.handleFunc[type]){if(this.handleFunc[type].indexOf(func)===-1){this.handleFunc[type].push(func);}}else{this.handleFunc[type]=[func];}};fire(type,func){try{if(arguments.length===1) {let target = this.handleFunc[type];let count = target.length;for (var i = 0; i < count; i++) {target[i]();}}else{let target = this.handleFunc[type];let index=target.indexOf(func);if(index===-1)throw error;func();}return true;}catch (e){console.error('别老想搞什么飞机,触发我有的东西!');return false;}};remove(type,func){try{let target = this.handleFunc[type];let index=target.indexOf(func);if(index===-1)throw error;target.splice(index,1);}catch (e){console.error('别老想搞什么飞机,删除我有的东西!');}};once(type,func) {this.fire(type, func)? this.remove(type, func): null;}
}

使用ES6的Reflect来实现一个观察者模式

[!NOTE]
函数(观察者)自动观察数据对象(观察的目标),一旦对象发生变化,函数就会自动执行

    // 观察者设计模式const queuedObservers = new Set();const observe = fn => queuedObservers.add(fn);const observable = obj => new Proxy(obj, {set});function set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);queuedObservers.forEach(observer => observer());return result;}// testconst person = observable({name: '张三',age: 20});function print() {console.log(`${person.name}, ${person.age}`)}observe(print);person.name = '李四';// 输出// 李四, 20

相关文章:

JavaScript 观察者设计模式

观察者模式:观察者模式&#xff08;Observer mode&#xff09;指的是函数自动观察数据对象&#xff0c;一旦对象有变化&#xff0c;函数就会自动执行。而js中最常见的观察者模式就是事件触发机制。 ES5/ES6实现观察者模式(自定义事件) - 简书 先搭架子 要有一个对象&#xff…...

鸿蒙进阶篇-网格布局 Grid/GridItem(二)

hello大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天让我们来继续学习鸿蒙进阶篇-网格布局 Grid/GridItem&#xff0c;上一篇博文我们已经学习了固定行列、合并行列和设置滚动&#xff0c;这一篇我们将继续学习Grid的用法&#xff0c;实现翻页滚动、自定义滚动条样式&…...

数据仓库之 Atlas 血缘分析:揭示数据流奥秘

Atlas血缘分析在数据仓库中的实战案例 在数据仓库领域&#xff0c;数据血缘分析是一个重要的环节。血缘分析通过确定数据源之间的关系&#xff0c;以及数据在处理过程中的变化&#xff0c;帮助我们更好地理解数据生成的过程&#xff0c;提高数据的可靠性和准确性。在这篇文章中…...

AndroidStudio-滚动视图ScrollView

滚动视图 滚动视图有两种: 1.ScrollView&#xff0c;它是垂直方向的滚动视图;垂直方向滚动时&#xff0c;layout_width属性值设置为match_parent&#xff0c;layout_height属性值设置为wrap_content。 例如&#xff1a; &#xff08;1&#xff09;XML文件中: <?xml ve…...

嵌入式硬件实战基础篇(一)-STM32+DAC0832 可调信号发生器-产生方波-三角波-正弦波

引言&#xff1a;本内容主要用作于学习巩固嵌入式硬件内容知识&#xff0c;用于想提升下述能力&#xff0c;针对学习STM32与DAC0832产生波形以及波形转换&#xff0c;对于硬件的降压和对于前面硬件篇的实际运用&#xff0c;针对仿真的使用&#xff0c;具体如下&#xff1a; 设…...

ElasticSearch的Python Client测试

一、Python环境准备 1、下载Python安装包并安装 https://www.python.org/ftp/python/3.13.0/python-3.13.0-amd64.exe 2、安装 SDK 参考ES官方文档: https://www.elastic.co/guide/en/elasticsearch/client/index.html python -m pip install elasticsearch一、Client 代…...

【eNSP】企业网络架构链路聚合、数据抓包、远程连接访问实验(二)

一、实验目的 网络分段与VLAN划分&#xff1a; 通过实验了解如何将一个大网络划分为多个小的子网&#xff08;VLAN&#xff09;&#xff0c;以提高网络性能和安全性。 VLAN间路由&#xff1a; 学习如何配置VLAN间的路由&#xff0c;使不同VLAN之间能够通信。 网络设备配置&am…...

独立站 API 接口的性能优化策略

一、缓存策略* 数据缓存机制 内存缓存&#xff1a;利用内存缓存系统&#xff08;如 Redis 或 Memcached&#xff09;来存储频繁访问的数据。例如&#xff0c;对于商品信息 API&#xff0c;如果某些热门商品的详情&#xff08;如价格、库存、基本描述等&#xff09;被大量请求…...

不一样的CSS(一)

目录 前言&#xff1a; 一、规则图形 1.介绍&#xff1a; 2.正方形与长方形&#xff08;实心与空心&#xff09; 2.1正方形&#xff1a; 2.2长方形 3.圆形与椭圆形&#xff08;空心与实心&#xff09; 3.1圆形与椭圆形 4.不同方向的三角形 4.1原理 4.2边框属性 5.四…...

题目:Wangzyy的卡牌游戏

登录 - XYOJ 思路&#xff1a; 使用动态规划&#xff0c;设dp[n]表示当前数字之和模三等于0的组合数。 状态转移方程&#xff1a;因为是模三&#xff0c;所以和的可能就只有0、1、2。等号右边的f和dp都表示当前一轮模三等于k的组合数。以第一行为例&#xff1a;等号右边表示 j转…...

国外云服务器高防多少钱一年?

国外云服务器高防多少钱一年&#xff1f;入门级高防云主机&#xff1a;这类主机通常具有较低的防御峰值&#xff0c;如30G或60G&#xff0c;价格相对较低。例如&#xff0c;30G峰值防御的高防云主机年费可能在2490元左右&#xff0c;而60G峰值防御的则可能在5044元左右。中等防…...

架构篇(04理解架构的演进)

目录 学习前言 一、架构演进 1. 初始阶段的网站架构 2. 应用服务和数据服务分离 3. 使用缓存改善网站性能 4. 使用应用服务器集群改善网站的并发处理能力 5. 数据库读写分离 6. 使用反向代理和CDN加上网站相应 7. 使用分布式文件系统和分布式数据库系统 8. 使用NoSQL和…...

【363】基于springboot的高校竞赛管理系统

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统高校竞赛管理系统信息管理难度大&#xff0c;容错率低&am…...

Spring Boot 监视器

一、Spring Boot 监视器概述 &#xff08;一&#xff09;什么是 Spring Boot 监视器 定义与作用 Spring Boot 监视器&#xff08;Spring Boot Actuator&#xff09;是一个用于监控和管理 Spring Boot 应用程序的工具集。它提供了一系列的端点&#xff0c;可以获取应用程序的运…...

Javascript如何获取指定网页中的内容?

这两天有一个需求&#xff0c;就是通过JS去获取网页的内容&#xff0c;当然&#xff0c;除了今天我要分享的这个方法以外&#xff0c;其实通过Ajax的Get方法也是可以实现这个功能的&#xff0c;但是Ajax就比较麻烦一些了&#xff0c;如果只是单纯的想要获取一下纯内容&#xff…...

第2章2.3立项【硬件产品立项的核心内容】

硬件产品立项的核心内容 2.3 硬件产品立项的核心内容2.3.1 第一步&#xff1a;市场趋势判断2.3.2 第二步&#xff1a;竞争对手分析1.竞争对手识别2.根据竞争对手分析制定策略 2.3.3 第三步&#xff1a;客户分析2.3.4 第四步&#xff1a;产品定义2.3.5 第五步&#xff1a;开发执…...

区块链:Raft协议

Raft 协议是一种分布式共识机制&#xff0c;这种机制适用于网络中存在一定数量的故障节点&#xff0c;但不考虑“恶意”节点的情况&#xff0c;所以更适合作为私有链和联盟链的共识算法。 在此协议中&#xff0c;每个节点有三种状态&#xff1a; 候选者 &#xff0c;可以被选…...

【C语言】位运算

我们在上学计算机的第一节课&#xff0c;就应该见过这些常见的运算符。然而&#xff0c;你可能有印象&#xff0c;但记不住众多操作符当中的位运算符&#xff0c;以及它们的作用和使用场景&#xff0c;我们的大脑会选择性地遗忘它认为没用的信息&#xff0c;存储下那些“有实际…...

计算机体系结构之多级缓存、缓存miss及缓存hit(二)

前面章节《计算机体系结构之缓存机制原理及其应用&#xff08;一&#xff09;》讲了关于缓存机制的原理及其应用&#xff0c;其中提出了多级缓存、缓存miss以及缓存hit的疑问。故&#xff0c;本章将进行展开讲解&#xff0c; 多级缓存、缓存miss以及缓存hit存在的意义是为了保持…...

【R78/G15 开发板测评】串口打印 DHT11 温湿度传感器、DS18B20 温度传感器数据,LabVIEW 上位机绘制演化曲线

【R78/G15 开发板测评】串口打印 DHT11 温湿度传感器、DS18B20 温度传感器数据&#xff0c;LabVIEW 上位机绘制演化曲线 主要介绍了 R78/G15 开发板基于 Arduino IDE 环境串口打印温湿度传感器 DHT11 和温度传感器 DS18B20 传感器的数据&#xff0c;并通过LabVIEW上位机绘制演…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上&#xff0c;对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...