概念
所谓迭代器,其实就是一个具有 next() 方法的对象,每次调用 next() 都会返回一个结果对象,该结果对象有两个属性,value 表示当前的值,done 表示遍历是否结束。
创建自己的迭代器:
function createIterator(items) {
var i = 0;
return {
next: function() {
var done = i >= item.length;
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
// iterator 就是一个迭代器对象
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // { done: false, value: 1 }
console.log(iterator.next()); // { done: false, value: 2 }
console.log(iterator.next()); // { done: false, value: 3 }
console.log(iterator.next()); // { done: true, value: undefined }
在for...of 使用:
var iterator = createIterator([1, 2, 3]);
for (let value of iterator) {
console.log(value);
}
结果报错 TypeError: iterator is not iterable,表明我们生成的 iterator 对象并不是 iterable(可遍历的)。
那什么才是可遍历的呢?
其实一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是“可遍历的”(iterable)。
ES6 规定,默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,或者说,一个数据结构只要具有 Symbol.iterator 属性,就可以认为是"可遍历的"(iterable)。
举个例子:
const obj = {
value: 1
};
for (value of obj) {
console.log(value);
}
// TypeError: iterator is not iterable
我们直接 for of 遍历一个对象,会报错,然而如果我们给该对象添加 Symbol.iterator 属性:
cost obj = {
value: 1
};
obj[Symbol.iterator] = function() {
return createIterator([1, 2, 3]);
};
for (value of obj) {
console.log(value);
}
// 1
// 2
// 3
由此,我们也可以发现 for of 遍历的其实是对象的 Symbol.iterator 属性。
默认可遍历对象
平时使用 for...of ,尽管我们没有手动添加 Symbol.iterator 属性,还是可以遍历成功,这是因为 ES6 默认部署了 Symbol.iterator 属性,当然我们也可以手动修改这个属性:
var colors = ["red", "green", "blue"];
colors[Symbol.iterator] = function() {
return createIterator([1, 2, 3]);
};
for (let color of colors) {
console.log(color);
}
// 1
// 2
// 3
数据结构默认部署了 Symbol.iterator 属性。
- 数组
- Set
- Map
- 类数组对象,如 arguments 对象、DOM NodeList 对象
- Generator 对象
- 字符串
模拟实现 for of
function forOf(obj, cb) {
let iterable, result;
if (typeof obj[Symbol.iterator] !== "function")
throw new TypeError(result + " is not iterable");
if (typeof cb !== "function") throw new TypeError("cb must be callable");
iterable = obj[Symbol.iterator]();
result = iterable.next();
while (!result.done) {
cb(result.value);
result = iterable.next();
}
}
网友评论