ES6中的for ... of循环和可迭代对象

2023-05-16

推荐教程:《JavaScript视频教程》

本文将研究 ES6 的 for ... of 循环。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

旧方法

在过去,有两种方法可以遍历 javascript。

首先是经典的 for i 循环,它使你可以遍历数组或可索引的且有 length 属性的任何对象。

for(i=0;i<things.length;i++) {
    var thing = things[i]
    /* ... */
}

其次是 for ... in 循环,用于循环一个对象的键/值对。

for(key in things) {
    if(!thing.hasOwnProperty(key)) { continue; }
    var thing = things[key]
    /* ... */
}

for ... in 循环通常被视作旁白,因为它循环了对象的每一个可枚举属性。这包括原型链中父对象的属性,以及被分配为方法的所以属性。换句话说,它遍历了一些人们可能想不到的东西。使用 for ... in 通常意味着循环块中有很多保护子句,以避免出现不需要的属性。

早期的 javascript 通过库解决了这个问题。许多 JavaScript库(例如:Prototype.js,jQuery,lodash 等)都有类似 each 或 foreach 这样的工具方法或函数,可让你无需 for i 或 for ... in 循环去遍历对象和数组。

for ... of 循环是 ES6 试图不用第三方库去解决其中一些问题的方式。

for … of

for ... of 循环

for(const thing of things) {
    /* ... */
}

它将遍历一个可迭代(iterable)对象。

可迭代对象是定义了 @@ iterator 方法的对象,而且 @@iterator 方法返回一个实现了迭代器协议的对象,或者该方法是生成器函数。

在这句话中你需要理解很多东西:

  • 可迭代的对象
  • @@iterator方法( @@是什么意思?)
  • 迭代器协议(这里的协议是什么意思?)
  • 等等,迭代(iterable)和迭代器(iterator)不是一回事?
  • 另外,生成器函数又是什么鬼?

下面逐个解决这些疑问。

内置 Iterable

首先,javascript 对象中的一些内置对象天然的可以迭代,比如最容易想到的就是数组对象。可以像下面的代码中一样在 for ... of 循环中使用数组:

const foo = [
'apples','oranges','pears'
]

for(const thing of foo) {
  console.log(thing)
}

输出结果是数组中的所有元素。

apples
oranges
pears

还有数组的 entries 方法,它返回一个可迭代对象。这个可迭代对象在每次循环中返回键和值。例如下面的代码:

const foo = [
'apples','oranges','pears'
]

for(const thing of foo.entries()) {
  console.log(thing)
}

将输出以下内容

[ 0, 'apples' ]
[ 1, 'oranges' ]
[ 2, 'pears' ]

当用下面的语法时,entries 方法会更有用

const foo = [
    'apples','oranges','pears'
]

for(const [key, value] of foo.entries()) {
  console.log(key,':',value)
}

在 for 循环中声明了两个变量:一个用于返回数组的第一项(值的键或索引),另一个用于第二项(该索引实际对应的值)。

一个普通的 javascript 对象是不可迭代的。如果你执行下面这段代码:

// 无法正常执行
const foo = {
  'apples':'oranges',
  'pears':'prunes'
}

for(const [key, value] of foo) {
  console.log(key,':',value)
}

会得到一个错误

$ node test.js
/path/to/test.js:6
for(const [key, value] of foo) {
TypeError: foo is not iterable

然而全局 Object 对象的静态 entries 方法接受一个普通对象作为参数,并返回一个可迭代对象。就像这样的程序:

const foo = {
  'apples':'oranges',
  'pears':'prunes'
}

for(const [key, value] of Object.entries(foo)) {
  console.log(key,':',value)
}

能够得到你期望的输出:

$ node test.js
apples : oranges
pears : prunes

创建自己的 Iterable

如果你想创建自己的可迭代对象,则需要花费更多的时间。你会记得前面说过:

可迭代对象是定义了  @@ iterator 方法的对象,而且  @@iterator 方法返回一个实现了 迭代器协议的对象,或者该方法是生成器函数。

搞懂这些内容的最简单方法就是一步一步的去创建可迭代对象。首先,我们需要一个实现 @@iterator 方法的对象。  @@ 表示法有点误导性,我们真正要做的是用预定义的 Symbol.iterator 符号定义方法。

如果用迭代器方法定义对象并尝试遍历:

const foo = {
  [Symbol.iterator]: function() {
  }
}

for(const [key, value] of foo) {
  console.log(key, value)
}

得到一个新错误:

for(const [key, value] of foo) {
                          ^
TypeError: Result of the Symbol.iterator method is not an object

这是 javascript 告诉我们它在试图调用 Symbol.iterator 方法,但是调用的结果不是对象。

为了消除这个错误,需要用迭代器方法来返回实现了迭代器协议的对象。这意味着迭代器方法需要返回一个有 next 键的对象,而 next 键是一个函数。

const foo = {
  [Symbol.iterator]: function() {
    return {
      next: function() {
      }
    }
  }
}

for(const [key, value] of foo) {
  console.log(key, value)
}

如果运行上面的代码,则会出现新错误。

for(const [key, value] of foo) {
                     ^
TypeError: Iterator result undefined is not an object

这次 javascript 告诉我们它试图调用 Symbol.iterator 方法,而该对象的确是一个对象,并且实现了 next 方法,但是 next 的返回值不是 javascript 预期的对象。

next 函数需要返回有特定格式的对象——有 value 和 done 这两个键。

next: function() {
    //...
    return {
        done: false,
        value: 'next value'
    }
}

done 键是可选的。如果值为 true(表示迭代器已完成迭代),则说明迭代已结束。

如果 done 为 false 或不存在,则需要 value 键。 value 键是通过循环此应该返回的值。

所以在代码中放入另一个程序,它带有一个简单的迭代器,该迭代器返回前十个偶数。

class First20Evens {
  constructor() {
    this.currentValue = 0
  }

  [Symbol.iterator]() {
    return {
      next: (function() {
        this.currentValue+=2
        if(this.currentValue > 20) {
          return {done:true}
        }
        return {
          value:this.currentValue
        }
      }).bind(this)
    }
  }
}

const foo = new First20Evens;
for(const value of foo) {
  console.log(value)
}

生成器

手动去构建实现迭代器协议的对象不是唯一的选择。生成器对象(由生成器函数返回)也实现了迭代器协议。上面的例子用生成器构建的话看起来像这样:

class First20Evens {
  constructor() {
    this.currentValue = 0
  }

  [Symbol.iterator]() {
    return function*() {
      for(let i=1;i<=10;i++) {
        if(i % 2 === 0) {
          yield i
        }
      }
    }()
  }
}

const foo = new First20Evens;
for(const item of foo) {
  console.log(item)
}

本文不会过多地介绍生成器,如果你需要入门的话可以看这篇文章。今天的重要收获是,我们可以使自己的 Symbol.iterator 方法返回一个生成器对象,并且该生成器对象能够在 for ... of 循环中“正常工作”。 “正常工作”是指循环能够持续的在生成器上调用 next,直到生成器停止 yield 值为止。

$ node sample-program.js
2
4
6
8
10

原文地址:https://alanstorm.com/es6s-many-for-loops-and-iterable-objects/

作者:Alan Storm

更多编程相关知识,请访问:编程学习网站!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ES6中的for ... of循环和可迭代对象 的相关文章

  • Node.js日志记录指南

    当你开始用 JavaScript 进行开发时 xff0c 可能学到的第一件事就是如何用 console log 将内容记录到控制台 如果你去搜索如何调试 JavaScript xff0c 会发现数百篇博文和 StackOverflow 文章
  • 软件测试的测试方法及测试流程

    一 测试方法 xff1a 白盒测试 xff1a 把软件比作一个打开的盒子 xff0c 可以看到软件代码的实现 xff0c 针对代码的实现验证代码是否存在问题 单元测试阶段采用的测试方法 灰盒测试 xff1a 介于白盒和黑盒测试之间 灰盒测试
  • 18个用于创建漂亮图表的JavaScript库推荐

    几乎不可能想象没有图形和图表的任何仪表盘 它们快速有效地呈现复杂的统计数据 此外 xff0c 一个好的图表还可以增强网站的整体设计 在本文中 xff0c 我将向您展示一些用于图形和图表的最佳JavaScript库 这些库将帮助您为将来的项目
  • JavaScript基础--引用数据类型 (对象)

    本文主要讲述了JavaScript对象的属性和对象的引用 xff0c 以及对象的读取 赋值 删除和获取对象键名的操作 1 对象 对象就是一组 键值对 xff08 key value xff09 的集合 xff0c 是一种无序的复合数据集合
  • javascript面向对象设计

    javascript和java语言不一样 xff0c 它没有类这个说法 xff0c 更没有子类父类一说 xff0c 所以它所谓的继承机制 xff0c 也是和其他语言完全不同的 创建对象三种方式 1 最简单的方式 xff0c 创建一个obje
  • 关键CSS和Webpack:自动最小化渲染阻止CSS

    消除渲染阻止的JavaScript和CSS 这是我始终坚持使用的Google Page Speed Insights建议 Google建议您在页面加载准备就绪时将最初需要的CSS 内插 CSS内嵌并加载CSS的其余部分 当访问web页面时
  • 如何用SASS编写可重用的CSS

    Sass是一个CSS预处理程序 xff0c 它在前端工程师的工具箱中变得至关重要 Sass之所以流行 xff0c 是因为它修复了几个CSS缺陷 相关推荐 xff1a css在线手册 这也是Bootstrap 4运行的基础 这意味着为了理解如
  • JS 变量的作用域及闭包

    与闭包有关的概念 xff1a 变量的作用域和变量的生存周期 下面本篇文章就来给大家介绍一下JS中变量的作用域及闭包 xff0c 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 一 变量的作用域 1 变
  • 理解JavaScript中的变量、范围和提升

    变量是许多编程语言的基本组成部分 xff0c 也是新手需要学习的第一个也是最重要的概念 JavaScript中有许多不同的变量属性 xff0c 以及命名变量时必须遵循的一些规则 在JavaScript中 xff0c 有三个关键字用于声明变量
  • 用于VueJS和Webpack的代码分割模式

    拆分单个页面应用程序的代码是提高其初始加载速度的一个很好的方法 由于用户不必一次性下载所有代码 xff0c 他们将能够更快地看到页面并与页面进行交互 这将提高用户体验 xff0c 特别是在移动领域 xff0c 这是搜索引擎优化的一个胜利 x
  • javascript掌握正则表达式

    正则表达式 xff08 英语 xff1a Regular Expression xff0c 在代码中常简写为regex regexp或RE xff09 使用单个字符串来描述 匹配一系列符合某个句法规则的字符串搜索模式 我想正则表达式之所以难
  • 知道要测试什么——Vue组件单元测试

    关于单元测试Vue组件 xff0c 我看到的最常见的问题是 我到底应该测试什么 虽然测试过多或过少都是可能的 xff0c 但我的观察是 xff0c 开发人员通常会在测试过多时犯错误 毕竟 xff0c 没有人愿意成为一个组件测试不足导致应用程
  • 软件测试 | 测试开发书单 | 测试工程师必读经典好书,你读过几本?

    测试好书1080 480 46 3 KB 软件测试入行容易进阶难 在持续交付体系背景下 xff0c 要成为测试开发高手意味着非常系统综合的知识储备 广泛阅读经典好书是快速成长的必要方式 霍格沃兹测试学院重点推荐几本测试经典好书以及必读清单
  • 使用webpack提升vue.js应用程序的四种方法

    Webpack是开发Vue js单页面应用程序的必要工具 通过管理复杂的构建步骤 xff0c 它使您的开发工作流更加简单 xff0c 并且可以优化应用程序的大小和性能 在本文中 xff0c 我将解释Webpack提升Vue应用程序的四种方法
  • 了解Node.js中的流(Stream)

    Node js 中的流 xff08 Stream xff09 是出了名的难用甚至是难以理解 用 Dominic Tarr 的话来说 xff1a 流是 Node 中最好的 xff0c 也是最容易被误解的想法 即使是 Redux 的创建者和 R
  • 深入了解Vue.js的作用域插槽

    作用域槽是Vue js的一个有用特性 xff0c 它可以使组件更加通用和可重用 唯一的问题是它们很难理解 试着让你的头在父母和孩子的范围内交织 xff0c 就像解决一个棘手的数学方程 当你不能很容易地理解某件事时 xff0c 一个好的方法是
  • JavaScript常用基础算法

    一个算法只是一个把确定的数据结构的输入转化为一个确定的数据结构的输出的function 算法内在的逻辑决定了如何转换 基础算法 一 排序 1 冒泡排序 冒泡排序function bubbleSort arr for var i 61 1 l
  • HTML中的meta标签属性的使用

    之前学习前端中 xff0c 对meta标签的了解仅仅只是这一句 lt meta charset 61 34 UTF 8 34 gt 但是打开任意的网站 xff0c 其head标签内都有一列的meta标签 下面我们就来详细介绍一下meta标签
  • 移动端H5开发常用小技巧(总结)

    本篇文章给大家整理一些在移动端H5开发常见的问题给大家做下分享 xff0c 这里很多是在开发过程中遇到的大坑或者遭到过吐糟的问题 xff0c 希望能给大家带来或多或少的帮助 html 篇 常用的meta属性设置 meta对于移动端的一些特殊
  • JavaScript中Switch语句的使用方法

    除了if else之外 xff0c JavaScript还有一个称为switch语句的功能 switch是一种条件语句 xff0c 它将针对多种可能的情况评估表达式 xff0c 并根据匹配的情况执行一个或多个代码块 switch语句与包含许

随机推荐

  • 如何构建可运行的JavaScript规范

    编程不仅仅是给计算机下达如何完成一项任务的指令 xff0c 它还包括以一种精确的方式与他人交流思想 xff0c 甚至是与未来的自己 这样的交流可以有多个目标 xff0c 也许是为了共享信息 xff0c 或者只是为了更容易地修改 如果你不理解
  • javascript中函数的5个高级技巧

    函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块 函数对任何一门语言来说都是一个核心的概念 xff0c 在javascript中更是如此 本文将深入介绍函数的5个高级技巧 作用域安全的构造函数 构造函数其实就是一个使用new操作符
  • 理解JavaScript中的原型和继承

    本文主要讲了原型如何在JavaScript中工作 xff0c 以及如何通过 Prototype 所有对象共享的隐藏属性链接对象属性和方法 xff1b 以及如何创建自定义构造函数以及原型继承如何工作以传递属性和方法值 介绍 JavaScrip
  • 大学毕业后转行软件测试我后悔了

    来自一篇新学员的留言 大学本科幼师专业 xff0c 家里人都想让我考教师资格证 xff0c 等毕业了当一名人民教师 xff0c 说这个职业是一辈子的铁饭碗 xff0c 风吹不着雨淋不到 xff0c 还有寒暑假 xff0c 找个离家近的 xf
  • 分享5个JS函数的高级技巧

    函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块 函数对任何一门语言来说都是一个核心的概念 xff0c 在javascript中更是如此 本文将深入介绍函数的5个高级技巧 作用域安全的构造函数 构造函数其实就是一个使用new操作符
  • 详解vue.js中watch的使用

    在vue中 xff0c 使用watch来响应数据的变化 watch的用法大致有三种 下面代码是watch的一种简单的用法 xff1a lt input type 61 34 text 34 v model 61 34 cityName 34
  • Vue中值得关注的21个开源项目(推荐)

    Vue 相对不于 React 的一个优点是它易于理解和学习 xff0c 且在国内占大多数 咱们可以在 Vue 的帮助下创建任何 Web 应用程序 因此 xff0c 时时了解一些新出现又好用的Vue 开源项目也是挺重要 xff0c 一方面可以
  • javaScript面向对象的三个基本特征介绍

    了解过面向对象的同学应该都知道 xff0c 面向对象三个基本特征是 xff1a 封装 继承 多态 xff0c 但是对于这三个词具体可能不太了解 对于前端来讲接触最多的可能就是封装与继承 xff0c 对于多态来说可能就不是那么了解了 封装 在
  • 7个实用的CSS background-image小技巧

    xff08 推荐教程 xff1a CSS教程 xff09 background image可能是我们所有人 xff08 前端开发人员 xff09 在我们的职业生涯中至少使用过几次的CSS属性之一 大多数人认为背景图像没有什么不寻常的 xff
  • 值得收藏的css grid构建复杂布局的小技巧!

    xff08 推荐教程 xff1a CSS教程 xff09 网格布局是现代CSS中最强大的功能之一 使用网格布局可以帮助我们在没有任何外部 UI 框架的情况下构建复杂的 快速响的布局 在这篇文章中 xff0c 将会介绍所有我们需要了解的 CS
  • 10个值得了解的Chrome开发工具和技巧

    1 模拟慢速网络和慢速设备 我们可能习惯了在城市的网速 xff0c 那是杠杠的 xff0c 并不意味网速在中国哪个都一样的 xff0c 在一些偏远地方 xff0c 网速依然慢的可怜 xff0c 所以有时候我们所做的产品是需要考虑网速慢的情况
  • JS中判断变量是否为数字方法

    推荐教程 xff1a JavaScript视频教程 JavaScript 是一种动态类型语言 xff0c 这意味着解释器在运行时确定变量的类型 实际上 xff0c 这也允许我们在相同的代码中使用相同的变量来存储不同类型的数据 如果没有文档和
  • vue+webpack2实现路由懒加载的方法介绍

    下面Vue js教程栏目给大家介绍一下vue 43 webpack2实现路由的懒加载的方法 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 当打包构建应用时 xff0c Javascript 包会变得
  • JS Math对象的10 个实用方法

    推荐教程 xff1a JavaScript视频教程 JavaScript中的math 对让我们能够对执行一些数学操作 它具有数学常数和函数的属性和方法 在今天的文章中将介绍 Math对象的一些有用方法 1 Math min Math min
  • PDF文档电子公章的初试

    PART 1 大家在日常生活中经常会接触到电子公章 xff0c 比如电子发票上一般会包含电子公章信息 xff0c 比如下图发票中就带有两个电子公章 xff0c 顶部的公章是普通的图形公章 xff0c 右下角的电子公章不仅包含图形公章还包含了
  • css grid构建复杂布局的小技巧

    xff08 推荐教程 xff1a CSS教程 xff09 网格布局是现代CSS中最强大的功能之一 使用网格布局可以帮助我们在没有任何外部 UI 框架的情况下构建复杂的 快速响的布局 在这篇文章中 xff0c 将会介绍所有我们需要了解的 CS
  • vue.js中使用v-for以及获取索引的方法介绍

    下面Vue js教程栏目带大家了解一下vue js中v for的使用及索引获取 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 2 x版本 xff1a v for 61 34 item index i
  • HTML网页自动跳转的5种方法

    xff08 推荐教程 xff1a html教程 xff09 在我们进行网站创建时经常会遇到需要进行网页跳转的情况 xff0c 本文就来为大家介绍五种网页自动跳转的方法 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望
  • 深入讨论JavaScript中Set对象如何让代码更快

    我确信有很多开发人员坚持使用基本的全局对象 xff1a 数字 xff0c 字符串 xff0c 对象 xff0c 数组和布尔值 对于许多用例 xff0c 这些都是需要的 但是如果想让你的代码尽可能快速和可扩展 xff0c 那么这些基本类型并不
  • ES6中的for ... of循环和可迭代对象

    推荐教程 xff1a JavaScript视频教程 本文将研究 ES6 的 for of 循环 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 旧方法 在过去 xff0c 有两种方法可以遍历 java