迭代的实战
我们知道很多迭代的操作,比如最经典的for,还有forEach,for of,for in等等,那么同样是迭代,我们该如何选择正确的迭代方式呢?下面来一一分析
forEach场景
forEach方法常见的可以遍历对象有Set,Map,array,NodeList,它会迭代每个数据结构知道终止,因为无法在内部使用return或者是break所以无法终止迭代,所以说如果我们的迭代无需终止,就可以使用forEach
let arr = [ {name:"猪痞恶霸",age:20}, {name:"Ned",age:21} ] arr.forEach((item) => { item.age+=1 }) 复制代码
比如使用forEach来对数组元素进行批量处理
for of场景
上面提到了forEach的迭代是无法终止的,所以当我们想终止迭代,那么我们就可以使用for of,比如在当元素满足某个条件的时候终止迭代
let arr = [1,3,10,7,10] for(item of arr) { console.log(item) if(item%2 === 0) { break } } // 1,3,10 复制代码
如上,当元素是偶数的时候那么就停止迭代,相对于forEach来看for of有个缺陷就是无法获取当前元素对应的索引,而forEach可以,所以我们需要选择不同的迭代操作来适应当前的需求。
for in场景
由于Object没有内置迭代器,所以for of无法对其进行迭代,我们可以使用for in方法来迭代对象,其返回的是属性的键名
let obj = { name:"ned", like:"man" } for(item in obj) { console.log(item) } // name like 复制代码
当然如果你想要针对对象进行一些特性地迭代,比如迭代Symbol属性,那么可以参考一下这篇文章:JS遍历对象的七种方法
Very Good!!!通过上面的三种迭代场景,我们学到了可以根据不同类型的迭代对象,参数需要,以及性能相关来判断使用哪种迭代操作,那么下面我给大家带来点花的:手撕迭代
手撕迭代
来源:JS高程4,下面我会根据这个手撕来给大家分析,帮助大家进一步透彻迭代
class Counter { constructor(limit) { this.limit = limit; } [Symbol.iterator]() { let count = 1, limit = this.limit; return { next() { if (count <= limit) { return { done: false, value: count++ }; } else { return { done: true, value: undefined }; } }, }; } } let counter = new Counter(3); for (let i of counter) { console.log(i); } 复制代码
这是一个实现迭代的类Counter,内部有构造函数与迭代器接口Symbol.iterator
- 创建实例的时候传入
limit给予实例长度,其实这里可以理解为我们在初始化数组的时候给与数组长度 - 进行
for of操作的时候对应内部Symbol.iterator方法并调用,返回一个迭代器对象,该对象包含一个next方法
// 内部机制 counter[Symbol.iterator]() // { // {next: ƒ} // } 复制代码
- 调用
next方法,返回{ done: false, value: count++ }格式数据,每次调用为count和limit做判断,如果超过范围,那么将返回的对象的done属性标记为false说明迭代完毕
最后
经过学长的鞭策与学姐的鼓励,我又一次地领悟了迭代器地奥妙,整理并输出了该篇文章,如果对你有帮助就点小爱心吧!