迭代器
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. java基础之线程池

    一.线程池:提前创建多个线程存放到集合容器中,其中的线程可以反复使用,减少资源的开销 作用就是:线程执行完一个任务,并不被销毁,而是可以继续执行其他的任务 使用线程池中线程对象的步骤: 1. 创建线程 ...

  2. Docker安装elasticsearch、kibana、ik分词器

    一.下载ealastic search和kibana,两者的版本要一致 docker pull elasticsearch:7.6.2 docker pull kibana:7.6.2 二.配置 mk ...

  3. mybatis——分页插件PageHelper的使用

    项目开发中涉及列表查询时,经常会需要对查询结果进行分页处理:常用的一个插件--PageHelper,是国内非常优秀的一款开源的mybatis分页插件,它支持基本主流与常用的数据库,一致支持mysql. ...

  4. MySQL 中使用索引一定有效吗?如何排查索引效果?

    MySQL 中使用索引一定有效吗?如何排查索引效果? 虽然索引是提升 MySQL 查询性能的常见手段,但并不是所有情况下索引都会有效.索引的使用取决于查询条件.数据分布.索引设计等多个因素.如果索引未 ...

  5. mysql免密登录

    开启mysql免密登录, vi /etc/my.cnf [mysqld]下添加 skip-grant-tables , 保存后重启mysql服务:service mysqld restart

  6. 【SQL周周练】一句 SQL 如何帮助 5 个人买到电影院最好的座位?

    大家好,我是"蒋点数分",多年以来一直从事数据分析工作.从今天开始,与大家持续分享关于数据分析的学习内容. 本文是第 3 篇,也是[SQL 周周练]系列的第 3 篇.该系列是挑选或 ...

  7. 反悔贪心&局部调整法学习笔记

    一.什么是反悔贪心 反悔贪心就是在普通贪心的过程中"反悔",从而使得一些看似不太好贪心的题变成贪心可做题. 二.反悔贪心普遍流程 就是先使用一个好想的贪心策略,使用优先队列进行维护 ...

  8. 基于Kubernetes可扩展的Selenium 并行自动化测试部署及搭建(2)——Win10环境下Kubernetes(k8s)部署

    继续上一篇,本篇进行K8S环境部署. K8s部署: 1.  访问k8s-for-docker-desktop 的github地址: https://github.com/AliyunContainer ...

  9. 递归神经网络 RNN 原理(上)

    前篇对于 RNN 前奏, 或者说是 NLP 的基础, 语言模型 (Language Model) 有了一点认识. LM 的应用场景为 在词库中, 搜索出 符合当前给定 句子的 下一个单词, 的所有可能 ...

  10. rancher 卸载后重装报错

    报错信息 kubectl create namespace cattle-system Error from server (InternalError): Internal error occurr ...