浅习一波JavaScript高级程序设计(第4版)p7-迭代器

简介: JavaScript 高级程序设计第 4 版(后简称高程4),相较于第 3 版,增加了 ES6 至 ES10 的全新内容,删除了旧版过时的内容,并在原有基础上充实了更加翔实的内容。中文译版于 2020 年发售,妥妥的“新鲜出炉”,你要是问本瓜:当今学 JavaScript 哪家强,我只能说:红宝书第 4 版最在行。

image.png


JavaScript 高级程序设计第 4 版(后简称高程4),相较于第 3 版,增加了 ES6 至 ES10 的全新内容,删除了旧版过时的内容,并在原有基础上充实了更加翔实的内容。

中文译版于 2020 年发售,妥妥的“新鲜出炉”,你要是问本瓜:当今学 JavaScript 哪家强,我只能说:红宝书第 4 版最在行。


于是乎,借着更文契机,本瓜将开启一个小系列,带你重看一遍高级程序设计4(先前只是跳着跳着看),将抽取精华,用最简单的话解释核心点、尽量把握全局、快速过一遍的同时,记录与工友们分享~~


正文



第七章,也是本瓜最感兴趣的一章之一 —— 《迭代器与生成器》(JavaScript 的延迟计算依赖的就是它),是重点毋庸置疑了。


ECMAScript 6 规范新增了两个高级特性:迭代器和生成器。使用这两个特性,能够更清晰、高效、方便地实现迭代。


本篇先只讲:迭代器,以及 for、forEach、for…in、for…of 的区别。

奥利给,冲!!


先回想,咱们以前是怎么去迭代的?

通常大部分情况下都是迭代数组吧?!


let arr = [1,2,3]
for (let index = 0; index < arr.length; index++) {
  console.log(arr[index]);
}


通过 for 循环去迭代,有什么问题吗?高程给出了解释:


  1. 迭代之前需要事先知道如何使用数据结构。 数组中的每一项都只能先通过引用取得数组对象, 然后再通过[]操作符取得特定索引位置上的项。并且,这种情况并不适用于所有数据结构。
  2. 遍历顺序并不是数据结构固有的。 通过递增索引来访问数据是特定于数组类型的方式,并不适 用于其他具有隐式顺序的数据结构。


什么意思?即: for 循环不适用遍历所有数据结构;


ES5 发布了 forEach ,并没有做出任何改善,反而也是弊端多多:

  1. 不能使用 break 语句中断循环;
  2. 不能使用 return 语句返回到外层函数;


for-in 呢?for-in 是为遍历普通对象设计的,可以得到字符串类型的键,不适用于数组遍历。


for-of 呢?没错,它是今天的主角!


for-of 循环语句通过方法调用来遍历各种集合:数组、NodeList、字符串、Maps 对象、Sets 对象等等


这些对象都有一个共通的特点:它们都有一个迭代器方法!


let str = 'abc';
let arr = ['a', 'b', 'c'];
let map = new Map().set('a', 1).set('b', 2).set('c', 3);
let set = new Set().add('a').add('b').add('c');
let els = document.querySelectorAll('div');
// 这些类型都实现了迭代器工厂函数
console.log(str[Symbol.iterator]); // f values() { [native code] }
console.log(arr[Symbol.iterator]); // f values() { [native code] }
console.log(map[Symbol.iterator]); // f values() { [native code] }
console.log(set[Symbol.iterator]); // f values() { [native code] }
console.log(els[Symbol.iterator]); // f values() { [native code] }
// 调用这个工厂函数会生成一个迭代器
console.log(str[Symbol.iterator]()); // StringIterator {}
console.log(arr[Symbol.iterator]()); // ArrayIterator {}
console.log(map[Symbol.iterator]()); // MapIterator {}
console.log(set[Symbol.iterator]()); // SetIterator {}
console.log(els[Symbol.iterator]()); // ArrayIterator {}


ES6 默认的 Iterator 接口部署在数据结构的 Symbol.iterator属性上,该属性本身是一个函数,代表当前数据结构默认的遍历器生成函数。执行该函数 [Symbol.iterator](),会返回一个遍历器对象。只要数据结构拥有 Symbol.iterator属性,那么它就是 “可遍历的” 。


原生具备 Iterator 接口的数据结构:

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象


它们其实就是默认的迭代器对象。


所有拥有 Symbol.iterator 的对象被称为可迭代的。


for...of 运行原理:


  1. 首先调用遍历对象 [Symobo.iterator]() 方法,拿到遍历器对象;
  2. 每次循环,调用遍历器对象 next() 方法,得到 {value: ..., done: ... } 对象


.next() 方法,返回:valuedone,如果 done 为 true,则代表:迭代已完成;


let arr = ['foo', 'bar'];
let iter = arr[Symbol.iterator]();
console.log(iter.next()); // { done: false, value: 'foo' }
console.log(iter.next()); // { done: false, value: 'bar' }
console.log(iter.next()); // { done: true, value: undefined }


我们可以尝试自己写一个极简版的迭代器对象:


class Counter {
   // Counter 的实例应该迭代 limit 次
   constructor(limit) {
    this.count = 1;
    this.limit = limit;
   }
   next() {
     if (this.count <= this.limit) {
         return { done: false, value: this.count++ };
     } else {
         return { done: true, value: undefined };
     }
   }
   [Symbol.iterator]() {
     return this;
   }
}


很神奇,不是吗?

咱就是说 ES6 为啥要搞一个迭代器呢,或者说迭代器的优势在哪里?


JavaScript 中 原有表示 “集合” 的数据结构主要是 “数组(Array)” 和 “对象(Object)”,ES6又新增了 MapSet,共四种数据集合,浏览器端还有 NodeList类数组结构。为 “集合” 型数据寻求统一的遍历接口,正是 ES6 的 Iterator 诞生的背景。


目的就是为了:统一!统一各种类型的集合,给出一种通用的、底层的迭代方案!

迭代器是一种设计模式,为遍历不同数据结构的 “集合” 提供统一的接口;能遍历访问 “集合” 数据中的项,不关心项的数据结构。


相关文章
|
7月前
|
前端开发 JavaScript 中间件
掌握JavaScript中的迭代器和生成器(下)
掌握JavaScript中的迭代器和生成器(下)
|
7月前
|
存储 JavaScript 前端开发
掌握JavaScript中的迭代器和生成器(上)
掌握JavaScript中的迭代器和生成器
106 0
|
6月前
|
存储 JavaScript 前端开发
javascript中的生成器和迭代器是什么
JavaScript中的生成器和迭代器是处理集合数据的利器,它们提供了一种遍历和操作元素的统一方式。迭代器是具有`next()`方法的对象,返回包含`value`和`done`属性的对象,用于循环处理集合。生成器函数更进一步,可以在执行过程中暂停并返回值,通过`yield`产生迭代值,适用于生成序列、异步编程和实现状态机等场景。例如,一个生成器可以无限生成斐波那契数列,或者在读取文件时控制异步流程。使用这些工具,代码变得更简洁、高效。
|
3月前
|
JavaScript 索引
|
4月前
|
存储 JavaScript 算法
JS程序设计的常用套路
亲尝百草,方知甘苦。套路,通常有助于提升代码的可读性、扩展性和效率。以下是作者工作中总结出来的一部分代码套路,分享给大家。
|
5月前
|
存储 JavaScript 前端开发
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二)
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二)
60 1
|
5月前
|
JavaScript 索引
JS的迭代器是啥?精读JS迭代器
JS的迭代器是啥?精读JS迭代器
37 0
|
5月前
|
存储 JavaScript 前端开发
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)
JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)
44 0
|
6月前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的程序设计基础视频学习系统附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的程序设计基础视频学习系统附带文章和源代码部署视频讲解等
40 0
|
JavaScript 前端开发
带你读《现代Javascript高级教程》十五、Iterator 迭代器:简化集合遍历的利器(1)
带你读《现代Javascript高级教程》十五、Iterator 迭代器:简化集合遍历的利器(1)