迭代器
概念:其实就是一个方法,也就是一个函数,主要目的是可以解决不同数据结构(Array,Set,Map,String)中获取数据的问题,统一了获取数据的方法。
就类似于java里面的implements,有一个叫做iteratorable的接口,然后里面有一个iterator的方法,其他类只要实现了,就可以让外部调用这个方法,去遍历得到这个数据结构的数据了。
在es6中,就是通过一个闭包生成一个遍历器方法,然后再不断地调用这个方法就可以得到元素的值了
听着高大上,其实我们完全可以自己模拟一个生成遍历器的方法
// 模拟一个数组的生成遍历器方法
function imitateIterator(array) {
var index = 0;
//判断游标是否已经超过数组长度,如果已经超过则代表已经遍历结束
function isDone() {
return index >= array.length;
}
//返回一个遍历器
return {
// 实现规范的遍历器函数,供外面调用
next: () => {
return {
value: !isDone() ? array[index++] : undefined,
done: isDone() //再次判断,因为index已经发生了变化
};
}
}
}
var array = imitateIterator([1,2,3]);
console.log(array.next());
console.log(array.next());
console.log(array.next());
console.log(array.next());
{ value: 1, isDone: false }
{ value: 2, isDone: false }
{ value: 3, isDone: true }
{ value: undefined, isDone: true }
由上面可以看出,其实就是在一个方法里面返回了一个闭包函数,就是我们的遍历器,通过这个遍历器,我们可以去获取它每个元素的值。
而在es6中,有一些数据结构已经有了内置的遍历方法了,也就是说已经实现了这个方法,用了[Symbol.iterator]
这个属性名去标识,原生具备 Iterator 接口的数据结构如下。
-Array
-Map
-Set
-String
-TypedArray
-函数的 arguments 对象
-NodeList 对象
[来自ECMAScript 6 入门]
也就是说比如
var originArr = [1,2,3];
//获取内置的遍历器方法
var iterator = originArr[Symbol.iterator]([1,2,3]);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
//set数据结构
var originSet = new Set(["a","b","v"]);
//获取内置的遍历器方法
var iterator = originSet[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
{ value: 'a', done: false }
{ value: 'b', done: false }
{ value: 'v', done: false }
{ value: undefined, done: true }
细心的同学可能会发现我最上面模拟的数组中value为3时的done值和原生数组实现的done值不一样,我的理解是当它遍历到最后一个的时候已经可以结束了,所以done是true,而可能标准中想保持value和done值的一致性吧,就是当value为undefined的时候done值才为false,不过这也说明了一个道理,其实遍历器都是可以由我们自己去实现和定义的拉!!
运用for of方法时就是去找它们的生成遍历器方法去自动遍历器的,但是这只针对对实现了这种方法的对象来说的,而es6对于Object是没有实现这种方法的,用这个方法则会报错,除非自己实现一个拉拉
var object = {
name: "fish",
general: "girl"
};
for(value of object) {
console.log(value);
}
//VM1515:7 Uncaught TypeError: object[Symbol.iterator] is not a function 报错拉拉
然后可以实现自己定义的遍历器方法
object[Symbol.iterator] = () => {
var index = 0;
var table = {
0: "name",
1: "general"
};//假设存储了对应关系
return {
next: function (argument) {
return index <= 1 ? {
value: object[table[index++]],
done: false,
} : {
value: undefined,
done: true
}
}
}
}
for(var value of object) {
console.log(value);
}
//fish
//girl
当然也可以覆盖掉原有的生成遍历器方法辣,在这里就不再写了,和上面的方式是一样的。还有以下也是调用iterator遍历器的
1.解构赋值
let [ first, ...second] = originSet;
console.log(first, second); //a [ 'b', 'v' ]
2....
扩展符
var string = "hello";
console.log([...string])
// [ 'h', 'e', 'l', 'l', 'o' ]
3.yield *
// yield*
function* test(argument) {
yield 1;
yield* [2,3,4];//调用数组的遍历器
yield 5;
}
var testIterator = test();
console.log(testIterator.next());
console.log(testIterator.next());
console.log(testIterator.next());
console.log(testIterator.next());
console.log(testIterator.next());
console.log(testIterator.next());
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: undefined, done: true }