ES6之Iterable
Iterable是ES6引入的一个新的类型。主要用于集合,对象的遍历。
一.引入的原因
- array可以使用下标遍历,而map,set不能使用下标遍历,集合类型不统一。
- 对于for…in…循环,当添加额外的属性后,会有意象不到的结果。
var array = [1,2,3]; array.name = 'name'; //for...in...遍历的是对象的属性。Array也是一个对象,他的每个元素的索引视为一个属性 for(var key in array) { console.log(key); //0 1 2 name }
因此,为了统一结合类型,ES6标准引入了新的iterable类型,统一使用iterable的for…of…循环进行遍历。
二.for…of…
for…of…是ES6新引入的语法,实现iterable的它的用法如下:
var array = [1,2,3];
var set = new Set(array);
var map = new Map([[0,'a'], [1,'b'], [2,'c']]);
for(var item of array) {
console.log(item);
}
// 1
// 2
// 3
for(item of set) {
console.log(item)
}
// 1
// 2
// 3
for(item of map) {
console.log(item[0]+ ' ' + item[1]);
}
// 0 a
// 1 b
// 2 c
for…of…循环修复了for…in…循环遍历属性的问题(但是不包括Array的length属性)。它只遍历集合本身的元素。
forEach遍历
forEach是ES5.1引入的语法,forEach函数接受一个回调函数,每次迭代都会自动调用该函数。
forEach遍历的使用方法
var array = [1, 2, 3];
var set = new Set(array);
var map = new Map([[1,'a'],[2,'b'],[3,'c']]);
array.forEach(function (value,index,array) {
console.log(value,index,array);
// 1 0 [ 1, 2, 3 ]
// 2 1 [ 1, 2, 3 ]
// 3 2 [ 1, 2, 3 ]
});
set.forEach(function (value,samevalue,set) {
console.log(value,samevalue,set);
// 1 1 Set { 1, 2, 3 }
// 2 2 Set { 1, 2, 3 }
// 3 3 Set { 1, 2, 3 }
});
map.forEach(function (value, key, map) {
console.log(value,key,map);
// a 1 Map { 1 => 'a', 2 => 'b', 3 => 'c' }
// b 2 Map { 1 => 'a', 2 => 'b', 3 => 'c' }
// c 3 Map { 1 => 'a', 2 => 'b', 3 => 'c' }
});
三.Iterables 和 Iterators
- 实现了Iterable Protocol的对象,成为可迭代对象,可以使用for…of…进行遍历.自定义的对象也可以实现这一属性,成为可迭代对象。
- 实现了 Iterator Protocol 的对象称为 迭代器对象,也就是我们说的迭代器对象。
Iterable Protocol : 需要实现一个 ECMA @@iterator 方法,即在键 [Symbol.iterator] 上提供一个方法。对象被 for…of 调用时,这个方法会被调用。方法应该返回一个迭代器对象(Iterator)用来迭代。
iterator Protocol:需要实现一个 next() 方法,每次调用会返回一个包含 value(当前指向的值)和 done(是否已经迭代完成)的对象。
Array的iterable实现方式
首先获取Array的Symbol.iterator属性,
var array = [1,2,3];
var itertor = array[Symbol.iterator]();
然后就可以通过调用迭代器对象的next()方法,进行遍历
console.log(itertor.next());
console.log(itertor.next());
console.log(itertor.next());
console.log(itertor.next());
// { value: 1, done: false }
// { value: 2, done: false }
// { value: 3, done: false }
// { value: undefined, done: true }
自定义Iterable对象
我们可以通过实现一个Symbol.iterable成为可迭代对象.
比如实现一个斐波那契数列:
let obj = {
[Symbol.iterator] () {
let a = 0,
b = 0;
return {
next () {
let value = 0;
if(!a) {
value = a = 1;
}
else if(!b) {
value = b = 1;
} else if (b < 50) {
value = a + b;
a = b;
b = value;
}
return {value, done: value === 0};
}
}
}
}
for(let i of obj) {
console.log(i);
}
使用Gengerator函数实现:Generator函数直接返回一个Iterator对象.
let obj2 = {
[Symbol.iterator]: function * () {
let a = 1,
b = 1;
yield a;
yield b;
while (b < 50) {
yield b = a + b;
a = b - a;
}
}
}
for(let i of obj2) {
console.log(i);
}