概念:
iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
1、为各种数据结构,提供一个统一的、简便的访问接口;
2、使得数据结构的成员能够按某种次序排列
3、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
工作原理:
- 创建一个指针对象(遍历器对象),指向数据结构的起始位置。 - 第一次调用next方法,指针自动指向数据结构的第一个成员 - 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员 - 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值,done: 布尔值} * value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束,在遍历过程中done始终是false * 当遍历结束的时候返回的value值是undefined,done值为true
原生具备iterator接口的数据(可用for of遍历):
1、Array 2、arguments 3、set容器 4、map容器 5、String 。。。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Iterator遍历器</title>
</head>
<body>
<script type="text/javascript">
//模拟一个Iterator接口
function myIterator(arr) {
let index = 0 // 记录指针的位置
return { // 这个对象的返回值就是一个对象指针
next:function () { // 在对象指针当中有一个next这样的方法对应一个函数
return index<arr.length ? {value:arr[index++],done:false} : {value:undefined,done:true} // 判断条件决定done的返回值
}
}
}
let arr = [1,40,'abc',true]
const it = myIterator(arr) // 这里将闭包返回值赋给一个常量,否则闭包会被回收,剩下的遍历又重新开始
console.log(it.next()) // {value: 1, done: false}
console.log(it.next()) // {value: 40, done: false}
console.log(it.next()) // {value: "abc", done: false}
console.log(it.next()) // {value: true, done: false}
console.log(it.next()) // {value: undefined, done: true}
console.log('----------------------')
// ES6已经设计好Iterator接口部署到指定的数据类型上,可以用for of去循环遍历
// 数组、字符串、arguments、set容器、map容器
for(let i of arr){
console.log(i) // 1 40 abc true
}
let str = 'ondean'
for(let i of str){
console.log(i) // o n e d e a n
}
function fun() {
for(let i of arguments){
console.log(i) // 100 200 false 'china'
}
}
fun(100,200,false,'china')
console.log('----------------------')
/*
底层实现原理:
对象的Symbol.iterator属性,指向该对象的默认遍历器方法,等同于是在指定的数据内结构部署Iterator接口
当使用for of去遍历某一个数据结构时,首先去找Symbol.iterator,找到了就去遍历,没有找到就不能遍历xxx is not iterator
*/
/*let obj = {
[Symbol.iterator]: function () {
let index = 0
return { // 这个对象的返回值就是一个对象指针
next:function () { // 在对象指针当中有一个next这样的方法对应一个函数
return index<this.length ? {value:this[index++],done:false} : {value:undefined,done:true} // 判断条件决定done的返回值
}
}
}
}*/
//如下:一个对象如果要具备可被for...of循环调用的Iterator接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)
class RangeIterator {
constructor(start, stop) {
this.value = start;
this.stop = stop;
}
[Symbol.iterator]() { return this; }
next() {
var value = this.value;
if (value < this.stop) {
this.value++;
return {done: false, value: value};
}
return {done: true, value: undefined};
}
}
function range(start, stop) {
return new RangeIterator(start, stop);
}
for (var value of range(0, 3)) {
console.log(value); // 0, 1, 2
}
console.log('----------------------')
//使用三点运算符、解构赋值默认原理是去调用Iterator接口
let arr2 = [1,6]
let arr3 = [2,3,4,5]
arr2 = [1,...arr3,6]
console.log(arr2) // (6) [1, 2, 3, 4, 5, 6]
let [x,y] = arr2
console.log(x,y) // 1 2
</script>
</body>
</html>