迭代器
es6新增的特性,之前没有,其语法借鉴了Python、 Java、 C++。

Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代List 和 Set 等集合。

实现了迭代器接口的类,都可以使用next方法来取元素。

比如:字符串、数组、映射、集合(Set、Map)、arguments 对象、NodeList 等 DOM 集合类型。

表现

const set = new Set();
set.add('共');
set.add('产');
set.add('党'); const setGen = set[Symbol.iterator](); // 取出迭代器:[Symbol.iterator]创建迭代器的工厂函数
const {done,value:fisrstEl} = setGen.next(); // 调用next取出第一个元素
let hasNext = !done; // 判断有没有元素标识
hasNext && console.log(fisrstEl, hasNext);
while(hasNext){
const {done, value} = setGen.next();
hasNext = !done;
hasNext && console.log(value, hasNext);
}

由上可以推断出:检查是否可以迭代 只需要判断是否存在默认迭代器属性的工厂函数[Symbol.iterator]即可知道

let num = 1;
let obj = {};
let str = 'abc';
// 这两种类型没有实现迭代器工厂函数
console.log(num[Symbol.iterator]); // undefined
console.log(obj[Symbol.iterator]); // undefined
// 这些类型都实现了迭代器工厂函数
console.log(str[Symbol.iterator]); // f values() { [native code] }

自己实现一个迭代器

举例,比如针对Object不支持迭代,所以我们帮其实现一个

const obj = {
name:'小明',
age:20,
[Symbol.iterator](){ // 迭代器工厂函数(用来生成迭代器的)
let index = 0;
return {
next:()=>{
const v = Object.keys(this)[index++];
return {done:!Boolean(obj), value:this[v]}
}
}
}
};
const objGen = obj[Symbol.iterator]();
console.log(objGen.next()); // {done: false, value: "小明"}
console.log(objGen.next()); // {done: false, value: 20}
console.log(objGen.next()); // {done: true, value: undefined}

利用生成器来简化迭代器的定义
如上代码,写起来很麻烦,比如我们需要一个index索引,通过自增来确定上一个和下一个。  我们还要写两个嵌套返回等等
所以es为我们提供一个内置办法,可以简化这些操作。

const obj = {
name:'小明',
age:20,
[Symbol.iterator]:function* (){ // 迭代器的生成器(用来取代迭代器工厂函数)
for (let index = 0; index < Object.keys(this).length; index++) {
const key = Object.keys(this)[index];
yield this[key]
}
}
};
const objGen = obj[Symbol.iterator]();
console.log(objGen.next()); // {done: false, value: "小明"}
console.log(objGen.next()); // {done: false, value: 20}
console.log(objGen.next()); // {done: true, value: undefined}

利用生成器来模拟同步代码

yield 关键字可以让生成器停止和开始执行,也是生成器最有用的地方。生成器函数在遇到 yield
关键字之前会正常执行。遇到这个关键字后,执行会停止,函数作用域的状态会被保留。停止执行的生
成器函数只能通过在生成器对象上调用 next()方法来恢复执行

这是红宝书 第4版的话,我们可以利用这个特性来模拟同步ajax

比如我有两个接口,代码如下:
api.js

/*
* 获取老师个人信息
**/
let getTcBasic = (tid) => {
const res = {
1: {
id: 1,
name: '小明',
age: 21,
sex: '男',
twfid: 2001
},
2: {
id: 2,
name: '小蓝',
age: 20,
sex: '男',
twfid: 2002
}
}
return new Promise((resolve) => {
setTimeout(function () {
resolve(res[tid]);
}, 1000);
});
}; /*
* 获取老师配偶信息
**/
const getTcWife = (twfid) => {
const res = {
2001: {
id: 2001,
name: '小红',
age: 18
},
2002: {
id: 2002,
name: '小白',
age: 19
}
}
return new Promise((resolve) => {
setTimeout(function () {
resolve(res[twfid]);
}, 2000);
});
}

实现代码如下

/*
* 循环运行gen(中yield工具 类似于三方包co的作用)
**/
const runGen = (gen, res) => {
const result = gen.next(res);
if (result.done) return;
result.value.then((res) => {
runGen(gen, res);
});
} /*
* 一个含有ajax请求的迭代器实例
* tip: 注意观察写法是不是很同步
**/
function getTcInfoGen(tid){
// 返回generator对象 (generator实例是可以被next分段执行,可以理解为可以分段执行的函数)
const generator = function* (){
console.log('第1次执行');
const tcBasicInfo = yield getTcBasic(tid); console.log('第2次执行');
const tcWifeInfo = yield getTcWife(tcBasicInfo.twfid); console.log('第3次执行');
console.log({...tcBasicInfo,tcWifeInfo});
}
return generator();
} /*
* 获取老师全部信息
**/
const getTcInfo = (tid) => {
console.log('请求中...');
const gen = getTcInfoGen(tid);
runGen(gen)
};
getTcInfo(1);

当然这只是js中同步需求的过度方案,最终还是要使用更加语义化es7中的async和await来  代替 function*和yield。
es7中的async和await是参考 function*和yield并做出了部分改良实现的

参考某位博主说的:
虽然Generator将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)。
此时,我们便希望能出现一种能自动执行Generator函数的方法。我们的主角来了async/await。

重新认识一下for...of

for循环的内部机制是:将可迭代对象利用next进行取值,然后将值再给调用者。
这也就意味着只有实现了原生的 iterator 接口,才能使用 for...of。
所以for...of不支持对象迭代。
那我们刚才给对象添加了迭代对象,自然是可以的,运行代码如下

const obj = {
name:'小明',
age:20,
[Symbol.iterator]:function* (){ // 迭代器的生成器(用来取代迭代器工厂函数)
for (let index = 0; index < Object.keys(this).length; index++) {
const key = Object.keys(this)[index];
yield this[key]
}
}
}; for (const iterator of obj) {
console.log(iterator);
}
// 小明
// 20

相比普通的for循环(也称计数循环),通过迭代器来实现的循环办法更加的方便和自由,因为可以自己实现迭代器,决定结果值。其他好处红宝书第4版所说:

1、迭代之前需要事先知道如何使用数据结构。
2、遍历顺序并不是数据结构固有的

其它

java语言更加完整和系统,所以用java去辅助理解js更加的通俗易懂和完整。

参考java的迭代器相关知识:https://www.runoob.com/java/java-iterator.html

js的集合有哪些?

js集合的概念是在es6中提出的,es5没有 这个概念,同样也是借鉴java等语言进行归纳。
原先可用于存储的有Object和Array,但是这些是有缺点的,至于哪些缺点,自己百度吧。
所以js又发明了新的概念,集合。
Map(以及其子类WeakMap)和Set(以及其子类WeakSet)

贴一张java集合的图

会发现,java的集合更加的全面,这也意味着,JavaScript以后还会对集合进行补充(因为存在这些集合类不是没有道理的,所以同样的js也会面临这些问题。所以慢慢扩充是必然的结果)。

同时也发现集合也都是实现了迭代器接口的。那就意味着集合都是可以迭代的,比如使用next()或者使用for...of。

es6的迭代器和生成器的更多相关文章

  1. 深入理解ES6之——迭代器与生成器

    迭代器 迭代器是被设计专用于迭代的对象,带有特定接口.所有的迭代器对象都有next方法,会返回一个结果对象.该结果对象有两个属性:对应下一个值的value,以及一个布尔类型的done,其值为true时 ...

  2. 深入理解ES6之迭代器与生成器

    迭代器 迭代器 iterator,在 Javascript 中,迭代器是一个对象(也可称作为迭代器对象),它提供了一个 next() 方法,用来返回迭代序列中的下一项. next 方法的定义,next ...

  3. 【ES6】迭代器与可迭代对象

    ES6 新的数组方法.集合.for-of 循环.展开运算符(...)甚至异步编程都依赖于迭代器(Iterator )实现.本文会详解 ES6 的迭代器与生成器,并进一步挖掘可迭代对象的内部原理与使用方 ...

  4. ES6深入浅出-4 迭代器与生成器-3.生成器 & for...of

    迭代器平时用的很少.但是如果你是写框架的,你会经常用到迭代器. 生成器是专门用来做迭代器的东西 发布器是要产生一个叫做next的对象,如果你要产生这种对象.就可以使用ES6新出的语法. ES6的新语法 ...

  5. 掌握JavaScript中的迭代器和生成器,顺便了解一下async、await的原理

    掌握JavaScript中的迭代器和生成器,顺便了解一下async.await的原理 前言 相信很多人对迭代器和生成器都不陌生,当提到async和await的原理时,大部分人可能都知道async.aw ...

  6. Python 从零学起(纯基础) 笔记 之 迭代器、生成器和修饰器

    Python的迭代器. 生成器和修饰器 1. 迭代器是访问集合元素的一种方式,从第一个到最后,只许前进不许后退. 优点:不要求事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而 ...

  7. Python之模块,迭代器与生成器

    本节涉及内容: 1. 迭代器和生成器 2. 递归 3. 字符串格式化 4. 模块 内置模块 自定义模块 第三方模块 5. 序列化的模块 json pickle (一). 迭代器和生成器: 迭代器:  ...

  8. Python之迭代器和生成器

    Python 迭代器和生成器 迭代器 Python中的迭代器为类序列对象(sequence-like objects)提供了一个类序列的接口,迭代器不仅可以对序列对象(string.list.tupl ...

  9. python学习笔记四 迭代器,生成器,装饰器(基础篇)

    迭代器 __iter__方法返回一个迭代器,它是具有__next__方法的对象.在调用__next__方法时,迭代器会返回它的下一个值,若__next__方法调用迭代器 没有值返回,就会引发一个Sto ...

  10. 【Python】迭代器、生成器、yield单线程异步并发实现详解

    转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...

随机推荐

  1. 树状数组(Fenwick Tree)原理和优化全面解析

    你正在开发一个交易系统,需要实时完成两种操作: 更新某个时间点的价格(单点修改) 快速计算某段时间段内的交易总量(区间查询) 当数据量较小时,我们可能会这样实现: vector<int> ...

  2. OpenStack 全套搭建部署指南(基于 Kolla-Ansible)

    一.环境准备 1. 硬件要求 控制节点:至少 4 核 CPU,8GB 内存,100GB 磁盘(推荐 SSD). 计算节点:根据虚拟机需求调整,建议 8 核 CPU,16GB 内存,200GB+ 磁盘. ...

  3. Spring基于注解的IOC配置

    目录 基于注解的IOC配置 1.用于创建对象的注解 2.用于注入数据的 3.用于改变作用范围的 和生命周期相关 基于注解的IOC配置 曾经XML的配置 <bean id="accoun ...

  4. 漏洞预警 | Ivanti Connect Secure栈溢出漏洞

    0x00 漏洞编号 CVE-2025-0282 0x01 危险等级 高危 0x02 漏洞概述 Ivanti Connect Secure是一款远程访问和零信任安全解决方案,它提供了SSL VPN功能, ...

  5. IDEA 项目目录如何显示target、idea文件夹(获取class文件)

    网上的解决方法大致有两种,如下: 方案一 勾选 Show Excluded Files 方案二 找到需要显示的文件夹并将它删除,下图以target文件夹为例 打开Settings -> Edit ...

  6. 手把手部署n8n

    n8n 是当前非常热门的开源 AI 工作流平台,在 GitHub 上已获得超过九万颗 star. 通过 n8n,用户可以拖拽节点,轻松搭建复杂的 AI 工作流.每个节点都支持上千种插件,可灵活集成各类 ...

  7. AutoCAD中的Deep Clone

    AutoCAD中的Deep Clone 所谓Deep clone是指将实体从一个dwg文件拷贝至另一个dwg文件,类似于Ctr+C,CtrV,而普通的实体的Copy()方法,是在单个dwg文件中输入命 ...

  8. Time Series in pandas

    Time Series import pandas as pd import numpy as np Date and Time data types and tools from datetime ...

  9. 第5讲、Transformer 编码器(Encoder)处理过程详解

    Transformer 编码器(Encoder)处理过程详解 Transformer Encoder 是一个由 N 层(一般为 6 层)堆叠而成的模块结构.每一层的本质是两个核心子模块: 多头自注意力 ...

  10. WPF 使用CompositionTarget.Rendering实现平滑流畅滚动的ScrollViewer,支持滚轮、触控板、触摸屏和笔

    之前的文章中用WPF自带的动画库实现了一个简陋的平滑滚动ScrollViewer,它在只使用鼠标滚轮的情况下表现良好,但仍然有明显的设计缺陷和不足: 没有实现真正的动画衔接,只是单纯结束掉上一个动画, ...