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

迭代器

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

next 方法的定义,next 方法是一个函数,执行后返回一个对象包含两个属性:{ done: [boolean], value: [any] }

function makeIterator(array) {var nextIndex = 0return {next() {return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { done: true }}}
}// iterator 是一个迭代器对象
var iterator = makeIterator([10, 20, 30])
iterator.next() // {value: 10, done: false}
iterator.next() // {value: 20, done: false}
iterator.next() // {value: 30, done: false}
iterator.next() // {done: true}

可迭代对象

可迭代对象必须实现一个 @@iterator 方法,也就是说在这个对象或者它的原型链上必须有一个方法名是 Symbol.iterator 的方法,当调用这个方法时它返回一个迭代器对象。

可迭代对象的表现形式为,可以使用 for...of 循环解构赋值拓展运算符(spread)yield* 这些语法来调用 Symbol.iterator 函数。也就是说这些语法糖在被调用时本质上都是在调用 Symbol.iterator 函数。

内置可迭代对象

String,Array,TypedArray,Map,Set,函数的arguments对象,NodeList对象都是内置的可迭代对象,他们的原型对象中都有一个 Symbol.iterator 方法。


// 可迭代对象
let iterable = [10, 20, 30]
// 继承自原型链
Symbol.iterator in iterable // true
iterable.hasOwnProperty(Symbol.iterator) // falsefor(let value of iterable){console.log(value)
}
// 10
// 20
// 30

自定义可迭代对象

字面量对象 let o = {} 默认没有 Symbol.iterator 方法,但是我们在对象上自定义一个 @@iterator 方法,此时字面量对象也可以使用 for...of循环,拓展运算符等等语法糖。


// 字面量对象默认是不可迭代对象
// 自定义对
var myIterable = {}
myIterable[Symbol.iterator] = function(){return {arr: [10, 20, 30],next: function(){if(this.arr.length > 0){return {value: this.arr.shift(), done: false}}else{return {done: true}}}}
}
[...myIterable] // [10, 20, 30]

生成器

生成器 generator,在 Javascript 中生成器是一个函数(也可称作生成器函数),它可以作为创建迭代器的工厂函数。生成器函数的返回值是一个迭代器对象,同时这个对象也是一个可迭代对象。

funtion* name(){ //statement } 这种声明方式可以定义一个生成器函数。

生成器函数的语法规则是,调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的 迭代器(iterator)对象。当这个迭代器的 next() 方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置为止,yield 后紧跟迭代器要返回的值。或者如果用的是 yield*(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。调用 next() 方法时,如果传入了参数,那么这个参数会作为上一条执行的 yield 语句的返回值。


// 生成器函数
function* generator(i){yield i + 1var y = yield 'foo'yield y
}var iterator = generator(10) // 此时生成器函数不执行,返回一个迭代器iterator.next()   // {value: 11, done: false} 
iterator.next()   // {value 'foo', done: false}
iterator.next(10) // {value: 10, done: false},将10赋值给上一条 yield 'foo' 左侧的值,即 y = 10,返回 y
iterator.next()   // {done: true}

既然 生成器函数 可以创建 迭代器对象,我们来试着将前面的例子用生成器函数的形式重写试试看。


// 生成器函数
function* makeIterator(array) {for (let i = 0; i < array.length; i++) {yield array[i]}
}// 迭代器对象,实现和上文一样的功能
var iteratorByGen = makeIterator([10, 20, 30])
iteratorByGen.next() // {value: 10, done: false}
iteratorByGen.next() // {value: 20, done: false}
iteratorByGen.next() // {value: 30, done: false}
iteratorByGen.next() // {done: true}

从上面的代码我们可以看到,利用生成器函数来创建一个迭代器对象的方式相比于之前我们普通函数创建的方式更加简洁,也更加清晰的表明调用生成器函数返回的是一个迭代器对象。除此之外还有什么区别呢。

上文已经提到,生成器函数返回的是一个 可迭代的迭代器对象,这是什么意思呢?看下代码就明白了。

// 生成器函数创建的迭代器对象
Symbol.iterator in iteratorByGen // true
[...iteratorByGen] // [10, 20, 30]// 普通函数创建的迭代器对象
Symbol.iterator in iterator // false
[...iterator] // Uncaught TypeError: iterator is not iterable

综上所述,我们可以确定的说 生成器函数是创建迭代器对象的语法糖 ,通过生成器函数我们可以用很简洁清晰的语法创建一个可迭代的迭代器对象。

来源:https://segmentfault.com/a/1190000017529530

转载于:https://www.cnblogs.com/qixidi/p/10185861.html

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

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

相关文章

强大的独立日期选择器(date picker)插件 - Kalendae

日期:2012-4-16 来源:GBin1.com 在线演示 本地下载 今天分享一个独立的日期选择插件Kalendae,Kalendae是 一个强大健壮的独立日期选择器。如果你不想使用重量的jQuery UI类库的话,这个插件肯定是一个不错的备选。Kalendae包含了…

35家名企嵌入式/软件秋招岗位等你来!

大家好,我是写代码的篮球球痴。前两天一个小伙伴在微信让我帮忙推荐嵌入式招聘岗位。我实话实说,是有认识的人让我推荐简历的,但是相对于专业的招聘网站,我手里能拿出来的岗位实在是少之又少,专业的招聘网站会对不同的…

javascript实现平滑的锚点

转到源文件 转载于:https://www.cnblogs.com/flat_peach/archive/2008/07/22/1248653.html

Windows下窗口的生命周期

程序的执行 当执行Windows程序的时候,加载器加载该程序,然后调用C startup code,再调用程序中WinMain()。 初始化 WinMain函数首先通过CreateWindow函数创建窗口,并对窗口进行初始化配置; 消息的处理 程序通过循环GetMessage函数不…

尝试梳理下ARM处理器的发展历史

大家好,这篇文章是我的朋友Michael Yao写的,我觉得非常不错,分享给大家。1. 前言本文尝试简单梳理下ARM处理器的发展历史、架构的演进,包括不同处理器的应用方向,但我们重点还是围绕Cortex-A系列展开,也会介…

linux下的CPU、内存、IO、网络的压力测试

一、对CPU进行简单测试: 1、通过bc命令计算特别函数 例:计算圆周率 echo "scale5000; 4*a(1)" | bc -l -q MATH LIBRARY If bc is invoked with the -l option, a math library is preloaded and the default scale is set to 20.…

清空sql server日志

1、打开查询分析器,输入命令DUMP TRANSACTION 数据库名 WITH NO_LOG2、打开企业管理器--右键你要压缩的数据库--所有任务--收缩数据库--收缩文件--选择日志文件--在收缩方式里选择收缩至: ,这里会给出一个允许收缩到的最小M数,直接输入这个数,确定就可以了。3、在数…

find与grep的区别

find 功能:在目录结构中搜索文件,并执行指定的操作。此命令提供了相当多的查找条件,功能很强大。 语法: find 查找位置 匹配文件名 说明:find命令从指定的起始目录开始,递归地搜索其各个子目录,查找满足寻…

给你这张图,你能搜索到来历吗

如果我们想让搜索引擎帮我们找到这张图的来历,可能吗? 这是目前搜索引擎做不到的。如果能做到呢? 转载于:https://www.cnblogs.com/shangge/archive/2008/07/23/1249767.html

晚上读内核代码

最近因为要解决一个bug,需要在内核的f_hid.c里面做一些适配,需要把这部分代码研究透彻。在这几天之前我是根本不知道什么是In端点,Out端点,以及什么是endpoint 0的,而且最近的一段时间,我一直是在写应用方面…

我的家庭私有云计划-16

嗯,上午测试S2S的稳定性,改掉几个bug。还挺忙的。这会儿让机器跑测试去,腾出点时间,我们接着聊。 呵呵,昨天哪,已经有朋友批评我了,说我有点贪大求全,这个论坛什么的没必要自己实现&…

采用存储复制方式同步数据,实现数据库安全升级

2017年年初,海天起点为某省中行机房搬迁工作保驾护航。在机房搬迁过程中发现有多套数据库需要升级到11g,但由于有些数据库比较老旧,升级过程不能一次性完成,需要先升级到一个中间版本,再升级到最终目标版本。 但由于银…

【转】娱乐八卦——关于孙悟空的授业师傅的分析

一.《西游记》和《封神演义》联系密切  提起明朝著作《西游记》和《封神演义》,我想你一定不会陌生。从两部作品中派生出来的《孙悟空大闹天宫》、《哪吒闹海》等神话就更是家喻户晓,人人皆知了。两部小说虽然讲述的是不同朝代的故事&#…

为啥要xargs

转载:http://blog.csdn.net/yhcharles/article/details/44875865 为啥要xargs? 通常linux命令可以用|首尾相连,上一个命令的 stdout 连接到下一个命令的 stdin。但是有些命令,比如ls、rm等,是从命令行参数接受输入的。这时候如果…

Linux进程调度与性能优化 | 真货

作者简介:张毅峰,某主机厂架构师。一、eBPF安全可观测性的前景展望本次分享将从监控和可观测性、eBPF安全可观测性分析、内核安全可观测性展望三个方面展开。1.监控(Monitoring)vs可观测性(Observability)从上图可以看到,监控只是可观测性的冰…

教师生涯由此开始

招聘会时间:2012-03-28 09:00 招聘会地址:就业办507 为加强教师队伍建设,建设教育强县,经研究,我县决定面向全国“985”、“211”工程高等师范院校应届毕业生选聘普通高中和初中教师38名。现将有关事项公告如下&#x…

AutoCAD .net 二次开发官方教程及源码C#版(4)-(源码下载)

示例源码第4章 数据库基础2:添加自定义数据在这一章中,我们将创建一个新的字典对象,它用来表示我们雇员就职的 ‘Acme 公司‘(呵呵,当然是虚构的一家公司)的部门。这个“部门”字典对象将包含一个表示部门经理的记录。…

二叉树前序、中序、后序遍历非递归写法的透彻解析

前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历。递归写法,只要理解思想,几行代码。可是非递归写法却很不容易。这里特地总结下,透彻解析它们的非递归写法。其中,中序遍历的非递归写法最简单,后序…

深夜看代码2

昨天的文章晚上读内核代码有人评论说好像说了一些什么,好像又没有说什么,所以我到底是在说什么呢?因为今天已经把内核修改好了,自己也测试了,所以这次好好说下,我到底是说了什么,又做了什么。—…

ecshop程序设置伪静态简单三步骤

ecshop相信很多做网站商城的站长朋友都会用到的程序,那么ecshop如何才能设置伪静态?之前本人在调整我这两个站时可费了我不少功夫;http://www.belle-china.com/;http://www.camel-hk.com/你们可以看到了吧我这两个站现在已经弄好了…