带你认识iterator
迭代器协议是什么
迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式。当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。
只要满足迭代器协议议的对象都可以成为迭代器,迭代器协议,是指对象要定义名为next的无参方法,并且next会返回一个对象,对象包含done(boolean)和value属性,比如:
var iterator = {
count : 0,
next : function(){
return {
done : this.count > 10,
value : this.count++
}
}
}
这就是一个迭代器
什么是可迭代协议
可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,例如,在一个 for..of 结构中,哪些值可以被遍历到。一些内置类型同时是内置可迭代对象,并且有默认的迭代行为,比如 Array 或者 Map,而其他内置类型则不是(比如 Object))。要成为可迭代对象, 一个对象必须实现 @@iterator 方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator 访问该属性
我理解的只要满足可迭代协议的对象,那么就认为这个对象是可迭代的,那么如何迭代呢?就需要对象自身或者原型链上定义迭代方法也就是Symbol.iterator.
Symbol.iterator返回的值就是一个满足迭代器协议的对象,比如:
var iteratorObject = {
[Symbol.iterator] : function(){
return iterator;
}
}
Symbol.iterator迭代器函数
这个函数很多js的内置对象中都有,比如Array、Set、Map、String等但是Object除外,而当我们使用这些对象的时候其实常用到这个函数。
for...of
在使用for...of去迭代一个对象的时候,就会调用此对象的迭代器函数,而如果这个对象是不是可迭代的,不满足迭代器协议,那么会抛出TypeError:object is not iterable
语法
for (variable of iterable) {
//statements
}
引用MDN的描述
variable : 在每次迭代中,将不同属性的值分配给变量。
iterable : 被迭代枚举其属性的对象。
从这里看,for...of一个可迭代对象的时候,会先执行对象的迭代器函数[Symbol.iterator]获取迭代器,获取带迭代器之后在执行迭代器的next()函数,将返回值赋值给for...of的变量
var iterator = {
count : 0,
next : function(){
console.log("执行了next");
return {
done : this.count > 10,
value : this.count++
}
}
}
var iteratorObject = {
[Symbol.iterator] : function(){
return iterator;
}
}
for(let i of iteratorObject){
console.log("在迭代了");
}
可以看到
每次迭代都是先执行一次next,然后把返回值赋值给变量,然后在执行for...of内部的部分
除了for...of还有yield*,结构赋值,展开语法(...)都会用到对象的迭代器方法