ECMAScript中迭代器的深入讲解

 更新时间:2021年08月06日 14:46:54   作者:木亦Sam  
在ECMAScript 6增加了一个对象,它不是新的语法或新的内置对象,而一种协议( 迭代器协议),所有遵守这个协议的对象,都可以称之为迭代器,这篇文章主要给大家介绍了关于ECMAScript中迭代器的相关资料,需要的朋友可以参考下

前言

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

较早的迭代

迭代肯定知道,简单理解起来就是循环,在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迭代器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • DEFER怎么用?

    DEFER怎么用?

    DEFER怎么用?...
    2006-07-07
  • js实现点击图片在屏幕中间弹出放大效果

    js实现点击图片在屏幕中间弹出放大效果

    这篇文章主要介绍了js实现点击图片在屏幕中间弹出放大效果,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • layui实现左侧菜单点击右侧内容区显示

    layui实现左侧菜单点击右侧内容区显示

    这篇文章主要为大家详细介绍了layui实现左侧菜单点击右侧内容区显示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Javascript实现时间倒计时功能

    Javascript实现时间倒计时功能

    这篇文章主要为大家详细介绍了Javascript实现时间倒计时功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • 通过js将26个英文字母按顺序依次排列方式

    通过js将26个英文字母按顺序依次排列方式

    这篇文章主要介绍了通过js将26个英文字母按顺序依次排列方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • JS一维数组转化为三维数组方法

    JS一维数组转化为三维数组方法

    这篇文章主要给大家分享了JS一维数组转化为三维数组的方法,下面文章围绕JS数组转换的相关资料展开内容,对大家的学习有一定的参考价值,需要的小伙伴可以参考一下
    2022-01-01
  • 前端项目中正确插入图片的不同方法和技术

    前端项目中正确插入图片的不同方法和技术

    本文详细介绍了在前端项目中插入图片的不同方法,包括HTML标签、CSS样式、JavaScript动态加载以及图片的性能优化,其中涉及到的技术包括响应式图片设计、图片懒加载技术和图片格式选择等,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • JS实现仿雅虎首页快捷登录入口及导航模块效果

    JS实现仿雅虎首页快捷登录入口及导航模块效果

    这篇文章主要介绍了JS实现仿雅虎首页快捷登录入口及导航模块效果,涉及JavaScript响应鼠标事件遍历页面元素的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • 如何利用原生JS实现图片预览加上传(前后端交互)

    如何利用原生JS实现图片预览加上传(前后端交互)

    在做网站系统时经常会用到图片上传功能,用户往往希望能看到自己上传的图片的样子,下面这篇文章主要给大家介绍了关于如何利用原生JS实现图片预览加上传,需要的朋友可以参考下
    2022-01-01
  • 如何让你的JavaScript函数更加优雅详解

    如何让你的JavaScript函数更加优雅详解

    在Js世界中有些操作会让你无法理解,但是却无比优雅,下面这篇文章主要给大家介绍了关于如何让你的JavaScript函数更加优雅的相关资料,需要的朋友可以参考下
    2021-07-07

最新评论