前端开发之迭代器模式

在前端开发中,设计模式是提升代码可读性、可扩展性和可维护性的关键。迭代器模式(Iterator Pattern)是行为型设计模式中的一种,能够让我们顺序访问一个集合中的元素,而不暴露其底层的结构。在 TypeScript 这样具有类型检查的语言中,迭代器模式应用更加方便。

简单for循环

迭代器模式解决的问题是如何更加方便,更加简易,更加友好地去遍历一个顺序集合。用for循环不就行了?不行,普通for循环不是迭代器,它有两个缺点,不符合我们的设计原则。

const arr = [10, 20, 30]
const length = arr.length
for (let i = 0; i < length; i++) {console.log(arr[i])
}

如上代码,首先需要知道数组的长度 length ,需要知道如何获取数组的元素 arr[i] 。这样就不符合高内聚低耦合的设计原则,这样数组的很多信息就被公开了。作为一个数组被公开没什么问题,但是如果这个数组是一个比较复杂的数据结构呢?或者第三方服务呢?把场景放大就会是很大的问题。所以普通for循环不是迭代器,迭代器解决的问题是解决数据源里面数据不确定问题、数据封装问题,更好地遍历有序集合的问题。

简易迭代器

const pList = document.querySelectorAll("p");
pList.forEach((p) => console.log(p));

这里没有使用for循环,而使用forEach,本质的区别是,forEach遍历的时候,不需要知道数组长度,也不需要知道怎么获取一个 元素,它直接通过参数传过来了。 

迭代器模式

UML类图如下:


class DataIterator {private data: number[];private index: number = 0;constructor(container: DataContainer) {this.data = container.data;}next() {if (this.hasNext()) {return this.data[this.index++];}return null;}hasNext() {return this.index < this.data.length;}
}class DataContainer {data = [10, 11, 12, 13, 14, 15];getIterator() {return new DataContainer(this);}
}const dataContainer = new DataContainer();
const dataIterator = new DataIterator(dataContainer);
while (dataIterator.hasNext()) {console.log(dataIterator.next());
}

以上输出结果和for循环遍历是一样的,但我们费这么大力气是为了什么呢?就是为了掩饰迭代器背后它是怎样不用for循环,不用获取长度、不用通过index获取数据的这种高内聚低耦合的方式,更符合设计原则:使用者和目标分离解耦;目标能自行控制其内部逻辑;使用者不关心目标的内部结构。 

 迭代器场景

1. 有序结构。包含:字符串、数组、NodeList等DOM集合、Map、Set、arguments

2. Symbol.iterator 

所有有序对象,都内置Symbol.iterator方法,执行该方法,会返回一个迭代器对象。

done为false,说明还没有到最后一个。和我们的 hasNext() 差不多。

我们可以自己定义一个迭代器。

interface IteratorRes {value: number | undefined;done: boolean;
}class CustomIterator {private length = 3;private index = 0;next(): IteratorRes {this.index++;if (this.index <= this.length) {return { value: this.index, done: false };}return { value: undefined, done: true };}[Symbol.iterator]() {return this;}
}const customIterator = new CustomIterator();
console.log(customIterator.next());
console.log(customIterator.next());
console.log(customIterator.next());
console.log(customIterator.next());

迭代器作用

1. 用于for of

只要有内置了Symbol.iterator,都可以执行。

const set = new Set([1, 2, 3]);
for (const num of set) {console.log(num);
}
const pList = document.querySelectorAll("p");
for (const p of pList) {console.log(p);
}
// 包括我们上面的例子
const customIterator = new CustomIterator();
for (const ci of customIterator) {console.log(ci);

2. 数组解构、扩展操作符、Array.from (可用于有任何迭代器模式的数据结构)

// 解构 数组
const arr = [10, 11, 12];
const [a1, a2] = arr;
console.log("a1", a1); // 10
console.log("a2", a2); // 11
// 解构 Set
const set = new Set([100, 200, 300]);
const [s1, s2] = set;
console.log("s1", s1); // 100
console.log("s2", s2); // 200// 扩展操作符
const arr = [10, 11, 12];
console.log([...arr]) // [10, 11, 12]
const set = new Set([100, 200, 300]);
console.log([...set]) // [100, 200, 300]// Array.form
console.log(Array.from(set)) // [100, 200, 300]

3. 用于创建Map和Set

4. 用于 Promise.all 和 Promise.race

5. 用于 yield*

Generator 生成器

function* getNums(){yield 10yield 20yield 30
}
const iterator = getNums()
console.log(iterator.next()) // {value: 10, done: false}
console.log(iterator.next()) // {value: 20, done: false}
console.log(iterator.next()) // {value: 30, done: false}
console.log(iterator.next()) // {value: undefined, done: true}
// 将上面的 console.log注释,接下来使用 for of
for (const number of iterator) {console.log(number) // 10 20 30
}

可见生成器返回的就是一个迭代器。

function* getNums(){yield* [10,20,30] // 有序结构,已经实现了[Symbol.Iterator]
}
const iterator = getNums()
for (const number of iterator) {console.log(number) // 10,20,30
}

接下来重构一下上面的 CustomIterator

class CustomIterator {private data: number[];constructor() {this.data = [10, 20, 30];}*[Symbol.iterator]() {yield* this.data;}
}
const iterator = new CustomIterator();
for (const n of iterator) {console.log(n); // 10 20 30
}

接下来我们使用 Generator + yield 深度优先遍历 DOM 树

<div id="app"><p><b>hello</b><i>world</i></p><p><img src="https://www.baidu.com/img/PCfb_5bf082d29588c07f842ccde3f97243ea.png" /></p>
</div>
function* traverse(elementList: Element[]): any {for (const element of elementList) {yield element;const children = Array.from(element.children);if (children.length) {yield* traverse(children);}}
}
const iterator = document.getElementById("app");
if (iterator) {for (const iteratorElement of traverse([iterator])) {console.log(iteratorElement);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/426857.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang | Leetcode Golang题解之第406题根据身高重建队列

题目&#xff1a; 题解&#xff1a; func reconstructQueue(people [][]int) (ans [][]int) {sort.Slice(people, func(i, j int) bool {a, b : people[i], people[j]return a[0] > b[0] || a[0] b[0] && a[1] < b[1]})for _, person : range people {idx : pe…

element-ui 日期选择器设置禁用日期

element-ui 日期选择器设置禁用日期 效果图如下&#xff1a; 2024-09-01 到2024-09-18之间的日期都不可选 2024-01-01之前的日期都不可选 官方文档中 picker-options 相关的介绍 实现功能&#xff1a; ​ 某仓库有限制最大可放置资产数量&#xff0c;且资产出借和存放都有…

高端论坛报告分享 | 李维森:中国地理信息产业发展报告(2024)

本报告为中国地理信息产业协会会长李维森在“2024中国地理信息产业大会”所作报告《中国地理信息产业发展报告&#xff08;2024&#xff09;》。转载请注明来源于中国地理信息产业协会。 本报告为中国地理信息产业协会会长李维森在“2024中国地理信息产业大会”所作报告《中国地…

Linux系统应用之知识补充——OpenEuler(欧拉)的安装和基础配置

前言 这篇文章将会对OpenEuler的安装进行详解&#xff0c;一步一步跟着走下去就可以成功 注意 &#xff1a;以下的指令操作最好在root权限下进行&#xff08;即su - root&#xff09; ☀️工贵其久&#xff0c;业贵其专&#xff01; 1、OpenEuler的安装 这里我不过多介绍&a…

GPT-4-Turbo 和 Claude-3.5-Sonnet 图片识别出答题的是否正确 进行比较

1、比较的图片&#xff1a; 使用GPT-4-Turbo 输入的 提问&#xff1a; 识别图片中的印刷字和手写字&#xff0c;如果写错的给一个正确答案 图片 回复&#xff1a; 在图片中&#xff0c;印刷字显示的是一系列的英语填空练习题&#xff0c;而手写字则是填入空白处的答案。以…

运行容器应用

kubernetes通过各种controller来管理pod的生命周期&#xff0c;为了满足不同的业务场景&#xff0c;kubernetes开发了Deployment&#xff0c;ReplicaSet&#xff0c;DaemonSet&#xff0c;StatefulSet&#xff0c;Job等多种ControllerDeployment&#xff1a; kubectl run nginx…

WebSocket 协议

原文地址&#xff1a;xupengboo WebSocket WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 在 WebSocket API 中&#xff0c;浏览器和服务器只需要完成一次握手&#xff0c;两者之间就直接可以创建持久性的连接&#xff0c;并进行双向数据传输。…

MYSQL出现“mysql不是内部或外部命令,也不是可运行的程序”

目录 1.配置环境变量 2.重新打开cmd测试 1.配置环境变量 进入mysql目录下的bin文件夹 复制目录 我们按下win&#xff0c;然后搜索“环境” 粘贴刚刚复制的目录 2.重新打开cmd测试 可以看到此时mysql正常

基于web的工作管理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

【Redis】Redis 典型应用 - 分布式锁原理与实现

目录 Redis 典型应⽤ - 分布式锁什么是分布式锁分布式锁的基础实现引⼊过期时间引⼊校验 id引⼊ lua引⼊ watch dog (看⻔狗)引⼊ Redlock 算法其他功能 Redis 典型应⽤ - 分布式锁 什么是分布式锁 在⼀个分布式的系统中&#xff0c; 也会涉及到多个节点访问同⼀个公共资源的…

飞书项目管理使用攻略

文章目录 项目管理项目管理的方法和工具项目管理方法&#xff1a;项目管理工具 飞书项目管理平台 创建空间需求管理缺陷管理人员排期飞书也可以创建敏捷开发管理.删除空间 参考文章 项目管理 项目管理是指在项目活动中运用专门的知识、技能、工具和方法&#xff0c;使项目能够…

Java面试篇基础部分-Java线程生命周期

线程的生命周期分别为 新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)这五种状态。   在系统运行过程中有线程不断地被创建,而旧的线程在执行完毕之后被清理,线程通过排队的方式获取共享资源或者锁的时候被阻塞,所以运行中的线程就会在…

如何让大模型更好地进行场景落地?

自ChatGPT模型问世后&#xff0c;在全球范围内掀起了AI新浪潮。 有很多企业和高校也随之开源了一些效果优异的大模型&#xff0c;例如&#xff1a;Qwen系列模型、MiniCPM序列模型、Yi系列模型、ChatGLM系列模型、Llama系列模型、Baichuan系列模型、Deepseek系列模型、Moss模型…

【数据结构】排序算法---快速排序

文章目录 1. 定义2. 算法步骤3. 动图演示4. 性质5. 递归版本代码实现5.1 hoare版本5.2 挖坑法5.3 lomuto前后指针 6. 优化7. 非递归版本代码实现结语 1. 定义 快速排序是由东尼霍尔所发展的一种排序算法。在平均状况下&#xff0c;排序 n 个项目要 O ( n l o g n ) Ο(nlogn) …

记录word转xml文件踩坑

word文件另存为xml文件后&#xff0c;xml文件乱码 解决方法&#xff1a; 1.用word打开.docx文件 2.另存为xml文件 3.点击工具 -> Web选项 -> 编码&#xff0c;选择UTF-8 4.点击确定 5.使用notpad打开xml文件 6.使用xml tool进行xml格式化即可。

【逐行注释】自适应Q和R的AUKF(自适应无迹卡尔曼滤波),附下载链接

文章目录 自适应Q的KF逐行注释的说明运行结果部分代码各模块解释 自适应Q的KF 自适应无迹卡尔曼滤波&#xff08;Adaptive Unscented Kalman Filter&#xff0c;AUKF&#xff09;是一种用于状态估计的滤波算法。它是基于无迹卡尔曼滤波&#xff08;Unscented Kalman Filter&am…

VMware vCenter Server 8.0U3b 发布下载,新增功能概览

VMware vCenter Server 8.0U3b 发布下载&#xff0c;新增功能概览 Server Management Software | vCenter 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vcenter-8-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysi…

无人机之控制距离篇

无人机的控制距离是一个复杂且多变的概念&#xff0c;它受到多种因素的共同影响。以下是对无人机控制距离及其影响因素的详细分析&#xff1a; 一、无人机控制距离的定义 无人机控制距离指的是遥控器和接收机之间的最远传输距离。这个距离决定了无人机在操作者控制下能够飞行的…

51单片机-直流电机(PWM:脉冲宽度调制)实验-会呼吸的灯直流电机调速

作者&#xff1a;Whappy&#xff08;菜的扣脚&#xff09; 脉冲宽度调制&#xff08;Pulse Width Modulation&#xff0c;PWM&#xff09;是一种通过调节信号的占空比来控制功率输出的技术。它主要通过改变脉冲信号的高电平持续时间相对于低电平的时间来调节功率传递给负载的量…

影刀RPA实战:网页爬虫之携程酒店数据

1.实战目标 大家对于携程并不陌生&#xff0c;我们出行定机票&#xff0c;住酒店&#xff0c;去旅游胜地游玩&#xff0c;都离不开这样一个综合性的网站为我们提供信息&#xff0c;同时&#xff0c;如果你也是做旅游的公司&#xff0c;那携程就是一个业界竞争对手&#xff0c;…