ECMAScript中迭代器的深入讲解

 更新时间:2021年8月6日 16:00  点击:2078

前言

许多初级前端开发者在往中级迈进的过程中,面试经常问到的一个就是迭代器和生成器,其实在开发中都用过,但是并不知道这是什么,或者有些许了解但并不够深入。那这篇文章就对这一部分开发者会有一定的帮助,讲清楚迭代器这玩意。

较早的迭代

迭代肯定知道,简单理解起来就是循环,在JavaScript 中,计数循环便是最简单的一种。示例:

for(let i = 0; i < 9; ++i){
	console.log("[ i ]", i);
}

迭代的基础就是循环,它包含几个必要条件:

  • 可以指定迭代的次数
  • 可以指定每次迭代执行的操作
  • 每次迭代都在下一次迭代开始前完成
  • 顺序都是事先定义好的

当需要循环遍历一个数组的时候,迭代是在一个有序的集合上进行的,「有序」即为数组中的所有元素都可以按照顺序从第一项到最后一项被遍历到。因为数组有确定的长度,以及每一项都可以通过索引下标去获取,也就是说可以通过索引去遍历整个数组。示例:

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 支持了迭代器模式。

迭代器模式

迭代器模式是一种非常抽象的说法,可以把它理解成数组或者集合这一类的对象,它们的元素是有限的,且互相独立无歧义。引用红宝书的解释,即为:

迭代器模式(特别是在ECMAScript这个语境下)描述了一个方案,即可以把有些结构称为“可迭代对象”(iterable),因为它们实现了正式的Iterable接口,而且可以通过迭代器Iterator消费。

迭代器工厂函数

迭代器工厂函数,也就是 Symbol.iterator(),它是大部分内置类型都含有的默认属性,通过它暴露 Iterable 接口(可迭代协议),也就是说要想数据类型支持迭代,那么该类型必须支持可迭代协议。

ECMAScript 中规定暴露的默认迭代器,必须以“Symbol.iterator”作为键,返回一个新的迭代器。检查是否存在默认迭代器属性的方法也很简单。示例:

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 }

写在最后

通过迭代器协议,你可以实现一个自定义的迭代器,比如规定迭代器可以被迭代的次数,或者提前终止迭代。

到此这篇关于ECMAScript中迭代器的文章就介绍到这了,更多相关ECMAScript迭代器内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • pytorch::Dataloader中的迭代器和生成器应用详解

    这篇文章主要介绍了pytorch::Dataloader中的迭代器和生成器应用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-30
  • ES6(ECMAScript 6)新特性之模板字符串用法分析

    这篇文章主要介绍了ES6(ECMAScript 6)新特性之模板字符串用法,简单介绍了ES6模板字符串的概念、功能并结合实例形式分析了ES6模板字符串的用法,需要的朋友可以参考下...2017-04-03
  • 关于ECMAScript中的原始值和引用值详解

    在ECMAScript中,变量可以存在两种类型的值,即原始值和引用,这篇这篇文章主要给大家介绍了关于ECMAScript中的原始值和引用值的相关资料,需要的朋友可以参考下...2021-08-04
  • C#特性-迭代器(上)及一些研究过程中的副产品

    这篇文章主要介绍了C#特性-迭代器(上)及一些研究过程中的副产品,需要的朋友可以参考下...2020-06-25
  • 一文读懂Java Iterator(迭代器)

    这篇文章主要介绍了Java Iterator(迭代器)的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-06
  • java迭代器和for循环优劣详解

    在本篇文章里小编给大家整理的是一篇关于java迭代器和for循环优劣详解内容,对此有兴趣的朋友们可以学习参考下。...2021-01-22
  • vector list map 遍历删除制定元素 防止迭代器失效的实例

    下面小编就为大家带来一篇vector list map 遍历删除制定元素 防止迭代器失效的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • 基于list循环删除元素,迭代器失效的问题详解

    下面小编就为大家带来一篇基于list循环删除元素,迭代器失效的问题详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • C++ 实现自定义类型的迭代器操作

    这篇文章主要介绍了C++ 实现自定义类型的迭代器操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-11
  • Python生成器与迭代器详情

    这篇文章主要介绍了Python生成器与迭代器,现在可以通过生成器来直接创建一个列表,是由于内存的限制,表的容量肯定是有限的,果我们需要一个包含几百个元素的列表,是每次访问的时候只访问其中的几个,剩下的元素不使用就很浪费内存空间,下面来了解具体内容...2021-11-02
  • 正确理解python迭代器与生成器

    在Python这门语言中,生成器毫无疑问是最有用的特性之一。与此同时,也是使用的最不广泛的Python特性之一。究其原因,主要是因为,在其他主流语言里面没有生成器的概念。本文将详细介绍python迭代器与生成器...2021-06-15
  • java中LinkedList使用迭代器优化移除批量元素原理

    本文主要介绍了java中LinkedList使用迭代器优化移除批量元素原理,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-11-01
  • ECMAScript中迭代器的深入讲解

    在ECMAScript 6增加了一个对象,它不是新的语法或新的内置对象,而一种协议( 迭代器协议),所有遵守这个协议的对象,都可以称之为迭代器,这篇文章主要给大家介绍了关于ECMAScript中迭代器的相关资料,需要的朋友可以参考下...2021-08-06
  • java迭代器中删除元素的实例操作详解

    在本篇内容里小编给各位分享了一篇关于java迭代器中删除元素的实例操作详解内容,有兴趣的朋友们可以学习下。...2021-01-22
  • C++实现LeetCode(173.二叉搜索树迭代器)

    这篇文章主要介绍了C++实现LeetCode(173.二叉搜索树迭代器),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-03
  • C#迭代器及Unity协程实例解析

    这篇文章主要介绍了C#迭代器及Unity协程实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-25
  • 实例讲解Python 迭代器与生成器

    这篇文章主要介绍了Python 迭代器与生成器的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-09
  • C#迭代器模式(Iterator Pattern)实例教程

    这篇文章主要介绍了C#迭代器模式(Iterator Pattern),包括了迭代器的适用范围及用法实例,需要的朋友可以参考下...2020-06-25
  • C++begin和end运算符的返回迭代器的类型如何判断?

    今天小编就为大家分享一篇关于C++begin和end运算符的返回迭代器的类型如何判断?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...2020-04-25
  • C#特性 迭代器(下) yield以及流的延迟计算

    这篇文章主要介绍了C#特性 迭代器(下) yield以及流的延迟计算,需要的朋友可以参考下...2020-06-25