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