迭代器
什么是迭代器
JavaScript 原有的表示“集合”的数据结构,主要是数组(Array
)和对象(Object
),ES6 又添加了Map
和Set
。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是Map
,Map
的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of
循环,Iterator 接口主要供for...of
消费。
内置的迭代器
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
可迭代对象
- 普通对象不可迭代,所以不能使用for...of...进行遍历
- 可迭代对象,或者说实现了迭代器的对象,可以使用for...of...进行遍历
const iterableObj = {
names: ['a', 'b', 'c'],
[Symbol.iterator]: function () {
let index = 0;
return {
next: () => {
return index < this.names.length
? { done: false, value: this.names[index++] }
: { done: true, value: undefined };
},
};
},
};
const iterator = iterableObj[Symbol.iterator]();
console.log(iterator.next()); //=> { done: false, value: 'a' }
console.log(iterator.next()); //=> { done: false, value: 'b' }
console.log(iterator.next()); //=> { done: false, value: 'c' }
console.log(iterator.next()); //=> { done: true, value: undefined }
// 普通对象是不能使用迭代器的
// const obj = {
// name: 'Alice',
// age: 19,
// sex: 'male',
// };
// for (let item of obj) {
// console.log(item); //=> TypeError: obj is not iterable
// }
// 可迭代的对象,或者说里面实现了迭代器的对象,是可以使用for...of...进行遍历的
for (let item of iterableObj) {
console.log(item); //=> a
//=> b
//=> c
}
封装一个数组的迭代器
const it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
function makeIterator(array) {
let nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}
自定义类的可迭代性
class Classroom {
constructor(address, name, students) {
this.address = address;
this.name = name;
this.students = students;
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
return index < this.students.length
? { done: false, value: this.students[index++] }
: { done: true, value: undefined };
},
};
}
}
const c1 = new Classroom('Beijing', 'Xuexi', ['Alice', 'Bruce', 'Celina']);
const iterator = c1[Symbol.iterator]();
console.log(iterator.next()); //=> { done: false, value: 'Alice' }
console.log(iterator.next()); //=> { done: false, value: 'Bruce' }
console.log(iterator.next()); //=> { done: false, value: 'Celina' }
console.log(iterator.next()); //=> { done: true, value: undefined }
console.log('------------------');
for (let item of c1) {
console.log(item);
//=> Alice
//=> Bruce
//=> Celina
}
迭代器的提前终止
- 迭代器如果执行iteator.return(),那么就会执行return()里面的语句
class Classroom {
constructor(address, name, students) {
this.address = address;
this.name = name;
this.students = students;
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
return index < this.students.length
? { done: false, value: this.students[index++] }
: { done: true, value: undefined };
},
return: () => {
console.log('迭代器提前终止了~~~');
},
};
}
}
const c1 = new Classroom('Beijing', 'Xuexi', ['Alice', 'Bruce', 'Celina']);
const iterator = c1[Symbol.iterator]();
console.log(iterator.next()); //=> { done: false, value: 'Alice' }
console.log(iterator.return());