这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战
迭代器
迭代器是一种特殊的对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔值,当没有更多可返回的数据时返回true。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每一次调用next()方法,都会返回下一个可用的值。 如果在最后一个值返回后在调用next()方法,那么返回对象中属性done的值为true,属性value则包含迭代器最终返回的值,这个返回值不是数据集的一部分,它与函数的返回值类似,是函数调用过程中最后一次给调用者传递信息的方法,如果没有相关数据则返回undefined。
生成器
生成器是一种返回迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的关键字yield。星号可以紧挨着function关键字,也可以在中间添加一个空格,比如这样:
function *createIterator() {
yield 1; yield 2; yield 3;
}let iterator = createIterator();
// 生成器的调用方式与普通函数一样,只不过返回的是一个迭代器console.log(iterator.next().value);
// console.log(iterator.next().value);
// console.log(iterator.next().value); // 3
使用yield关键字可以返回任何值或表达式,所以可以通过生成器函数批量地给迭代器添加元素。例如,可以在循环中使用yield关键字
function *createIterator(items) {
for (let i = 0; i < items.length; i++)
{
yield items[i];
}}
let iterator = createIterator([1,2,3]);
// 生成器的调用方式与普通函数一样,只不过返回的是一个迭代器console.log(iterator.next());
// {value: 1, done: false}console.log(iterator.next());
// {value: 2, done: false}console.log(iterator.next());
// {value: 3, done: false}console.log(iterator.next());
// {value: undefined, done: true}// 之后所有的调用都会返回相同的内容
console.log(iterator.next());
// {value: undefined, done: true}
yield关键字只可在生成器内部使用,在其他地方使用会导致程序跑出语法错误,即便在生成器内部的函数里使用也是如此;
生成器函数式表达式
let createIterator = function *(items) {
// 代码块}
这个示例和前面的是相同的
不能使用箭头函数来创建生成器
可迭代对象和for-of循环
可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。Symbol.iterator通过指定的函数可以返回一个作用于附属对象的迭代器。在ECMAScript6中,所有的集合对象(数组,Set集合和Map集合)和字符串都是可迭代对象,这些对象中都有默认的迭代器。ECMAScript中新加入的特性for-of循环需要用到可迭代对象的这些功能。
由于生成器默认会为Symbol.iterator属性赋值,因此所有通过生成器创建的迭代器都是可迭代对象
for-of循环没执行一次都会调用可迭代对象的next()方法,并将迭代器返回结果对象的value属性存储在一个变量中,循环将持续执行这一过程直到返回对象的done属性为true。比如下面这个示例:
let values = [1,2,3];
// 正常的for-or循环使用
for (let num of values) {
console.log(num);}
// 打印结果:
// 1
// 2
// 3
// 访问默认迭代器,如下
let iterator = values[Symbol.iterator]();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
检测对象是否为可迭代对象
function isIterable(object) {
return typeof object[Symbol.iterator] === 'function';}
console.log(isIterable([1,2,3])); // true
console.log(isIterable('hello')); // true
console.log(isIterable(new Map())); // true
console.log(isIterable(new Set())); // true
console.log(isIterable(new WeakMap())); // false
console.log(isIterable(new WeakSet())); // false
内建迭代器
集合对象迭代器
在ECMAScript6中有3种类型的集合对象:数组,Map集合和Set集合。为了更好地访问对象中的内容,这3种对象都内建了以下三种迭代器:
- entries() 返回一个迭代器,其值为多个键值对。
- values() 返回一个迭代器,其值为集合的值。
- keys() 返回一个迭代器,其值为集合中的所有键名。
- entries()迭代器
每次调用next()方法时,entries迭代器都会返回一个数组,数组中的两个元素分别表示集合中每个元素的键与值。如果被遍历的对象是数组,则第一个元素是数字类型的索引;如果是Set集合,则第一个元素与第二个元素都是值(Set集合中的值被同时作为键与值使用);如果是Map集合,则第一个元素为键名。下面是entries()迭代器的使用示例:
entries()迭代器
let colors = ['red', 'green', 'blur'];
let tracking = new Set([132, 465, 956]);
let data = new Map();
data.set('title', 'ECMAScript 6');
data.set('format', 'ebook');
for(let entry of colors.entries()) {
console.log(entry);}
// 打印结果
// [0, 'red']
// [1, 'green']
// [2, 'blur']
for(let entry of tracking.entries()) {
console.log(entry);}
// 打印结果
// [132, 132]
// [465, 465]
// [956, 956]
for(let entry of data.entries()) {
console.log(entry);}
// 打印结果
// ['title', 'ECMAScript 6']// ['format', 'ebook']
values()迭代器
调用values()迭代器时会返回集合中所存的所有值,例如:
let colors = ['red', 'green', 'blur'];
let tracking = new Set([132, 465, 956]);
let data = new Map();
data.set('title', 'ECMAScript 6');
data.set('format', 'ebook');
for(let entry of colors.values()) {
console.log(entry);}
// 打印结果
// 'red'
// 'green'
// 'blur'
for(let entry of tracking.values()) {
console.log(entry);}
// 打印结果
// 132
// 465
// 956
for(let entry of data.values()) {
console.log(entry);}
// 打印结果
// 'ECMAScript 6'
// 'ebook'
keys()迭代器
keys()迭代器会返回集合中存在的每一个键。如果遍历的是数组,则会返回数字类型的键,数组本身的其它属性不会被返回;如果是Set集合,由于键与值是相同的,因此keys()和values()返回的也是相同的迭代器;如果是Map()集合,则keys()迭代器返回每个独立的键。看下面这个示例:
let colors = ['red', 'green', 'blur'];
let tracking = new Set([132, 465, 956]);
let data = new Map();
data.set('title', 'ECMAScript 6');
data.set('format', 'ebook');
for(let entry of colors.keys()) {
console.log(entry);}
// 打印结果
// 0
// 1
// 2
for(let entry of tracking.keys()) {
console.log(entry);}
// 打印结果
// 132
// 465
// 956
for(let entry of data.keys()) {
console.log(entry);}
// 打印结果
// 'title'
// 'format'
前端路漫漫其修远兮,吾将上下而求索,一起加油,学习前端吧
欢迎留言讨论~