ES6_Iteration protocols

ES6中新增了iterable protocol和iterator protocol,即可迭代协议和
迭代器协议,前者规定JavaScript对象可以自定义本身被遍历时的行为,后者规定了作为一个迭代器应有的标准方法。(遍历和迭代意思差不多)

一、iterable protocol 可迭代协议

遵循了这个协议的JavaScript对象都可以称为iterable objects,即可迭代的对象,很多JavaScript内建对象都遵循了这个协议(包括Array,Map,Set,String,TypeArray,arguments,Generator实例等等)。那么怎么算遵循了这个协议呢?

只要实现了@@iterator方法,即只要对象本身或其原型链上有[Symbol.iterator]属性,该属性值为无参函数,且该函数返回一个遵循iterator protocol(下面会说明)的对象(iterator迭代器)。

栗如:

1
2
3
4
var str = "abc", //String遵循iterable protocol
var array = [1,2,3]; //Array遵循iterable protocol
typeof str[Symbol.iterator] // 结果为function
typeof array[Symbol.iterator] //结果为function

遵循了这个协议然后呢?
遵循iterable protocol协议的对象在被迭代时(如被for…of,spread oprator扩展运算符,yield*操作时),会调用其@@iterator方法,即调用obj[Symbol.iterator]方法,并返回一个iterator对象,当然该iterator对象遵循iterator protocol,下面会提到。

二、for…of

for…of语句用来循环迭代一个可被迭代的对象(iterable objects),语法为

for (variable of iterable) {statement}

iterable即iterable objects,将该object的内的值遍历出来并复制给variable;
更多for…of的栗子请看MDN大法好

三、iterator protocol 迭代器协议

遵循这个协议的对象都可以称为iterator,即迭代器。那么怎么算遵循了这个协议呢?

当对象实现了一个next()方法,且该方法满足以下条件。
该方法返回一个包含两个属性值的对象一个为done的boolean属性,true时表示 迭代至最后一个值,false表示非最后一个值,false等同于没有指定done属性;一个为value属性,可以为任何JavaScript值,在done属性为true时被忽略。

栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var str = "abc";
var iter = str[Symbol.iterator](); //拿到String的迭代器
iter.next(); //{value:"a",done:false}
iter.next(); //{value:"b",done:fasle}
iter.next(); //{value:"c",done:true}
for(var value of str){ //for...of自动连续调用迭代器的next方法
consle.log(value); //a,b,c
}
1,客官可以把for..of中的str换成iter,发现结果仍一样...,说明撒?
说明iter这个迭代器本身也遵循了iterable protocol协议,
试试:
typeof iter[Symbol,iterator] //"function"
2,我擦?再来看这个:
iter[Symbol,iterator]===iter //true
原来String迭代器不仅遵循iterator protocol,也遵循iterable protocol,且其[Symbol.iterator]()方法返回的就是自己。
返回第一个问题,为啥写成str和iter迭代结果一样呢?因为for...of会去拿str的迭代器,即iter,并调用iter的next方法,你写成iter,for...of找到就是它,所以结果一样。
很多对象本身即遵循iterator protocol,也遵循iterable protocol,例如逼格稍高的Generator实例对象,理解本章对理解generator非常有益。
3,调用iter的next()方法可以看到返回符合iterator protocol协议的值,value和done;

四、自定义对象被迭代时的行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var someString = new String("abc");
someString[Symbol.iterator] = function() {
return {
next: function() {
if (this._first) {
this._first = false;
return { value: "bye", done: false };
} else {
return { done: true };
}
},
_first: true
};
};
for(var value of someString){
console.log(value); //"bye"
}
如上修改了someString的默认的[Symbol.iterator]方法,并且返回了一个迭代器对象,该迭代器对象指定了someString第一次返回"bye",第二次被迭代时done为true,停止迭代。
注意自定义的迭代器最好有结束迭代的设置,即要有done为true的情况,否则for...of会一直调用next()方法,直到遇见done为true才停止,没有的话就TM成死循环了。

更详细的内容请看MDN