迭代 iteration
迭代:按照顺序反复多次执行一段程序,通常会有明确的终止条件,会在一个有序集合上进行。
迭代器的优点
- 开发者无需事先知道如何迭代,就能实现迭代操作。
- 为各种不同的数据结构,提供统一的访问机制。详细来说,
实现Iterator接口的结构---都可以消费---实现Iterable接口(可迭代协议)的数据结构。迭代器无需了解与其关联的可迭代对象的结构,只需要知道如何取得连续的值。
如何实现Interable接口(可迭代协议)?
- 使数据结构具有
Symbol.iterator属性。 一个数据结构只要具有Symbol.iterator属性,就是可遍历的。 Symbol.iterator属性值为一个函数,执行这个函数就会返回一个遍历器对象。遍历器对象必须具有next()方法 (return()和throw()是可选的),每次调用next方法,都会返回一个代表当前成员的信息对象。- 这个
当前成员的信息对象具有value和done两个属性。
原生具备Iterable接口的数据结构(7):
- Array数组
- Map映射
- Set集合
- String字符串
- TypedArray类数组
- 函数的arguments对象
- NodeList等DOM集合
通过Iterable接口实现的迭代语言结构:
- for-of
- 解构赋值(对数组解构赋值、对Set解构赋值) 对数组和Set解构赋值时,会默认调用Symbol.iterator方法。
- 扩展操作符(...) 扩展运算符会调用默认的Symbol.iterator方法。
- Array.from()
- 创建集合 ( new Set() )
- 创建映射 ( new Map(['a', 1]) )
- Promise.all() 接收由Promise组成的可迭代对象
- Promise.racel() 接收由Promise组成的可迭代对象
- yield操作符 yield操作符,在生成器中使用,后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
使用Generator函数实现Symbol.iterator()方法,是最简单的Symbol.iterator()方法实现。
遍历器对象的 return(),throw()
遍历器对象除了具有next()方法,还可以具有return()方法和throw()方法。如果你自己写遍历器对象生成函数,那么next()方法是必须部署的,return()方法和throw()方法是否部署是可选的。
return()方法的使用场合是,如果for...of循环提前退出(通常是因为出错,或者有break语句),就会调用return()方法。如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return()方法。
注意,return()方法必须返回一个对象,这是 Generator 语法决定的。
throw()方法主要是配合 Generator 函数使用,一般的遍历器对象用不到这个方法。请参阅《Generator 函数》一章。
迭代和遍历、循环、递归 的区别
迭代器模式
迭代器模式:开发者无须事先知道如何迭代就能实现迭代操作。
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示。
可迭代对象
实现了[Symbol.iterator]方法。
实现了Iterable接口,而且可以通过迭代器Iterator消费。
==实现了[Symbol.iterator]方法的可迭代对象才可以被迭代型语言结构操作/使用/消费。==
可迭代协议
实现Iterable接口必须:支持迭代的自我识别能力、创建实现Iterator接口对象 的能力。
1.具有Symbol.iterator属性
2.Symbol.iterator属性的属性值为一个函数。
此函数返回值为next()函数,next()返回值为一个包含两个属性的对象,done表示是否还有更多值可以访问,true表示已经遍历完,函数停止执行。false表示下一次仍执行next()函数。value表示当前值,默认undefined。
//迭代器实现原理 (取value值)
//对象没有实现Iterable接口,所以需要手动添加Symbol.iterator属性
let obj = {
a:1,
b:2,
c:3
};
obj[Symbol.iterator] = function() {
let values = Object.values(obj);
let index = 0;
return {
next() {
if(index >= values.length){
return {
done:true
}
} else {
return {
done:false,
value:values[index++] //++:以便下次index指向values下一项
}
}
}
}
};
//for-of这种迭代型语言结构就是通过调用数据结构的Symbol.iterator属性的函数实现的
for (let val of obj){
console.log(val);
}
//输出:1
// 2
// 3
//迭代器实现原理 (取key:value值)
//对象没有实现Iterable接口,所以需要手动添加Symbol.iterator属性
let obj = {
a:1,
b:2,
c:3
};
obj[Symbol.iterator] = function() {
let keys = Object.keys(obj);
let index = 0;
return {
next() {
if(index >= values.length){
return {
done:true
}
} else {
return {
done:false,
value:{
key:keys[index],
value:obj[keys[index++]] //++:以便下次index指向values下一项
}
}
}
}
}
};
//for-of这种迭代型语言结构就是通过调用数据结构的Symbol.iterator属性的函数实现的
for (let val of obj){
console.log(val);
}
//输出:{key:"a", value: 1}
// {key:"b", value: 2}
// {key:"c", value: 3}