这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战前端
许多初级前端开发者在往中级迈进的过程当中,面试常常问到的一个就是迭代器和生成器,其实在开发中都用过,可是并不知道这是什么,或者有些许了解但并不够深刻。那这篇文章就对这一部分开发者会有必定的帮助,讲清楚迭代器这玩意。web
迭代确定知道,简单理解起来就是循环,在JavaScript 中,计数循环即是最简单的一种。示例:面试
for(let i = 0; i < 9; ++i){
console.log("[ i ]", i);
}
复制代码
迭代的基础就是循环,它包含几个必要条件:数组
当须要循环遍历一个数组的时候,迭代是在一个有序的集合上进行的,「有序」即为数组中的全部元素均可以按照顺序从第一项到最后一项被遍历到。由于数组有肯定的长度,以及每一项均可以经过索引下标去获取,也就是说能够经过索引去遍历整个数组。示例:markdown
const arr = ["a", "b", "c"];
for(let i = 0; i < arr.length; ++i){
console.log(arr[i]);
}
复制代码
可是这种模式必需要事先知道使用的是什么数据结构,例如数组,若是换成其它数据类型,或者具备隐式顺序的数据结构,那么遍历的顺序就不可肯定。 因而在 ES5 中新增了forEach()
方法。示例:数据结构
const arr = ["a", "b", "c"];
arr.forEach(item=>{
console.log(item);
});
复制代码
这个方法就不用同数组索引去遍历和获取单项的取值,但没法标识迭代何时结束,所以仅适用于数组的遍历。为了解决这些问题,ES6 以后,JavaScript 支持了迭代器模式。函数
迭代器模式是一种很是抽象的说法,能够把它理解成数组或者集合这一类的对象,它们的元素是有限的,且互相独立无歧义。引用红宝书的解释,即为:post
迭代器模式(特别是在ECMAScript这个语境下)描述了一个方案,便可以把有些结构称为“可迭代对象”(iterable),由于它们实现了正式的Iterable接口,并且能够经过迭代器Iterator消费。网站
迭代器工厂函数,也就是 Symbol.iterator(),它是大部份内置类型都含有的默认属性,经过它暴露 Iterable 接口(可迭代协议),也就是说要想数据类型支持迭代,那么该类型必须支持可迭代协议。 ECMAScript 中规定暴露的默认迭代器,必须以“Symbol.iterator”做为键,返回一个新的迭代器。检查是否存在默认迭代器属性的方法也很简单。示例:ui
const obj = {};
const arr = ["a", "b", "c"];
console.log(obj[Symbol.iterator]); // underfined
console.log(arr[Symbol.iterator]); // f values() { [native code] }
console.log(arr[Symbol.iterator]()); // ArrayIterator {}
复制代码
固然,咱们实际开发中是不用显示调用迭代器工厂函数的,支持可迭代协议的数据类型会自动兼容接受可迭代对象的任何语言特性,例如当咱们使用循环、for-of、解构、扩展操做符的时候,会自动在后台调用提供的可迭代对象的迭代器工厂函数,从而建立一个迭代器。
迭代器协议约定迭代器是一种一次性使用的对象,当调用迭代器工厂函数后,返回一个next()
方法,每一次迭代成功都会调用该方法,得知下一个迭代的值,若是不调用,则不肯定迭代的当前位置。 next()
方法返回一个对象,包含量属性:done
和value
,done 表示是否能够继续调用next()
方法获取下一个值,意为是否「耗尽」,返回一个 Boolean 值; value 表示可迭代对象的下一个值。done 为 true 时,value 则为 underfined。done 为 false 时,则会继续调用下一个迭代。示例:
// 可迭代对象
let arr = ['foo', 'bar'];// 迭代器工厂函数
console.log(arr[Symbol.iterator]);// f values() { [native code] }
// 迭代器
let iter = arr[Symbol.iterator]();
console.log(iter); // ArrayIterator{}
// 执行迭代
console.log(iter.next()); // { done: false, value: 'foo' }
console.log(iter.next()); // { done: false, value: 'bar' }
console.log(iter.next()); // { done: true, value: undefined }
复制代码
经过迭代器协议,你能够实现一个自定义的迭代器,好比规定迭代器能够被迭代的次数,或者提早终止迭代。
写做不易,但愿能够得到你的一个「赞」。若是文章对你有用,能够选择「收藏」。 若有文章有错误或建议,欢迎评论指正,谢谢你。❤️