ES6学习之路:迭代器Iterator和生成器Generator

在这里插入图片描述

迭代器

一、知识背景

  1. 什么是迭代器
    迭代器就是在一个数据集合中不断取出数据的过程
  2. 迭代和遍历的区别
    • 遍历是把所有数据都取出
    • 迭代器注重的是依次取出数据,它不会在意有多少数据,也不会保证能够取出多少或者能够把数据都取完。比如斐波那契额数列,就可以使用迭代器进行无限取值。
  3. 那么,什么是迭代器呢?
    对整个迭代过程的封装,不同的语言有不同的表现形式。通常是一个对象
  4. 迭代模式
    一个设计模式,用于统一迭代过程,并规范了迭代器规格
    • 迭代器应该具有得到下一个数据的能力
    • 迭代器应该具有判断是否还有后续数据的能力

二、ES6里的迭代器

JS中规定,如果一个对象具有next方法,并且该方法返回一个对象,则该对象的格式如下,则认为该对象是一个迭代器。

const obj={
  next(){
     retrun{
         value:xxx, // 值
         done:xxx// 是否迭代完成
     }
  }
}

在这里插入图片描述

  • next方法:用于得到下一批数据
  • 返回的对象
    • value:下一个数据的值
    • done:布尔值,是否完成迭代

三、迭代器创建函数

这个知识点分两个方面来分享 1. 迭代对象内置的迭代器创建函数 2.创建自定义的可迭代对象

3.1、 迭代对象内置的迭代器创建函数

首先,我们需要搞懂什么是迭代器创建函数?

  • ES6规定,如果一个对象具有知名符号属性 [Symbol.iterator],并且属性是一个迭代器创建函数,则该对象是可迭代的(iterable)

    • 迭代器(iterator):一个具有next方法的对象,next方法返回下一个数据并且能指示是否迭代完成
    • 迭代器创建函数(iterator create):一个返回迭代器的函数

js中的可迭代对象有很多,例如数组,集合,映射,类数组,字符串等,以数组为例


  const arr=[1,3,4,5,6]
  console.log(arr)

在这里插入图片描述

执行数组中的迭代器

// 数组
const arr = [1, 2, 3, 4, 5];
// 数组中内置的迭代器创建函数
const iterator = arr[Symbol.iterator]()
// 执行迭代器
iterator.next()

在这里插入图片描述
执行类数组中的迭代器,例如 document.querySelectorAll

// 类数组内置的迭代器
const divs=document.querySelectorAll('div')
const iterator=divs[Sysbol.iterator]()
iterator.next() 

3.2、 普通对象自定义创建 迭代器创建函数

通常,我们使用for of 循环遍历可迭代对象

// 迭代完成后循环结束
for(const item in iterable){
	 // iterable:可迭代对象
	 // item 每次迭代得到的数据
}

可以发现,forof是无法遍历普通对象的,那是因为普通对象不是迭代对象,没有迭代器创建函数和[Symbol.iterator]属性,如果我把这个属性给它加上,普通对象是否会成为迭代对象,从而被forof遍历呢?

// 自定义的可迭代对象
var obj = {
a:1,
b:2,
  [Symbol.iterator]() {
    return {
      next() {
        return {
          value: 1,
          done: false
        }
      }
    }
  }
}
for(const item of obj){
   console.log(item)
}

在这里插入图片描述

在这里插入图片描述
结果发现,普通对象是可以通过添加迭代创建函数的方式成为迭代对象的,forof会不断的获取 迭代器中的value值,只要done不为false,就会一直无限取下去。

生成器

一、知识背景

  1. 什么是生成器?
    生成器是一个通过构造函数Generator创建的,也是一个对象,但是无法自己new,只能js引起内部去使用;生成器即是一个迭代器,同事也是一个迭代对象。

  2. 如何创建一个生成器?

    生成器的创建必须使用生成器函数 (Generator Function),返回的是一个生成器对象

  3. 如何书写一个生成器函数呢?

    
     // 这是一个生成器函数,该函数一定返回一个生成器
     function *method(){
     	
     }
    
     function* method(){
     	
     }
    
     {
     	*method(){
     		
     	}
     }
    
     *methods=()=>{}
    
    
  4. 生成器函数是如何执行的?

    • 生成器函数内部是给生成器每次迭代提供数据的,生成的数据需要放在yield后,才能被迭代出来

          function* test() {
       		 console.log('aaaa') 
       		 
       }
       const generator = test()
       console.log(generator.next()) //  aaaa  { value: undefined, done: true }
      

      在这里插入图片描述

    • yield 是一个关键词,该关键词只能在生成函数的内部使用,意思是 “产生” 一个迭代数据

    • 每次调用生成器的next方法,生成器将运行到下一个yield的位置

      function* test() {
       	console.log('第一次运行')
       	yield 1; //产生的迭代数据
       	console.log('第二次运行')
       	yield 2;//产生的迭代数据
       	console.log('第三次运行')
       }
       const generator = test()
       console.log(generator.next()) // 第一次运行 { value: 1, done: false }
       console.log(generator.next()) // 第二次运行 { value: 2, done: false }
       console.log(generator.next()) // 第三次运行 { value: undefined, done: true }
      
    • 生成器可以有返回值return 返回值出现在当迭代器next方法中的done为true时的 value中

      function* test() {
       	console.log('第一次运行')
       	yield 1; //产生的迭代数据
       	console.log('第二次运行')
       	yield 2;//产生的迭代数据
       	console.log('第三次运行')
       	return 10; //函数结束,迭代结束,所以迭代器第一次done为true 的value值可以为10 
       }
       
       const generator = test()
       console.log(generator.next()) // 第一次运行 { value: 1, done: false }
       console.log(generator.next()) // 第二次运行 { value: 2, done: false }
       console.log(generator.next()) // 第三次运行 { value: 10, done: true }
       console.log(generator.next()) /  { value: undefined, done: true }
      
    • 调用next(参数)方法传值,参数会传给第一次next后的yield,所以第一次调用next(),传参是没有意思的

         function* test() {
        	let info = yield 1 // { value: 1, done: false }
        	console.log(info) // 5
        	info = yield 2 + info // { value: 7, done: false }
        	console.log(info)
        }
        const generator = test()
        
        console.log(generator.next(111)) // { value: 1, done: false }
        console.log(generator.next(5)) // { value: 7, done: false }
      
    • 在生成器内部调用其他生成器的函数的迭代数据,注意调用时要加*

         fucntion *a(
            yield 'a'
            yield 'b'
         )
         function *test(){
                // a() 返回一个生成器对象
                // yield a() 迭代一个生成器对象
                yield *a()
                yield 1
        	    yield 2
        	   yield 3
        } 
        const generator = test()
        console.log(generator.next()) // { value: 'a', done: false } // 会先迭代a方法里的数据
      

二、 生成器常见的api使用方法

除了next方法,下面再接收两个用的比较多的方法

return方法

return方法,调用该方法,可以手动结束整个迭代,后面再次调用next方法时,value值为 undefined

	function* test() {
		yield 1
		yield 2
	    yield 3
	}
	const generator = test()
	console.log(generator.next()) //  { value: 1, done: false }
	console.log(generator.return()) // { value: undefined, done: true }
	console.log(generator.next()) // { value: undefined, done: true }
	console.log(generator.next()) // { value: undefined, done: true }
	console.log(generator.next()) // { value: undefined, done: true }
	// return 也可以传参数
	console.log(generator.return(5)) // { value: 5, done: true }

throw方法

throw方法,调用该方法,可以手动抛出一个错误,从而阻止后面数据的迭代

function* test(){
     yield 1
     yield 2
     yield 3
}
const generator = test()
console.log(generator.next()) //  { value: 1, done: false }
console.log(generator.throw(new Error('123'))) // 在  yield 1 报错
console.log(generator.next()) // 不运行
console.log(generator.next()) // 不运行 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/487263.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入解析Mybatis-Plus框架:简化Java持久层开发(十三)

🍀 前言 博客地址: CSDN:https://blog.csdn.net/powerbiubiu 👋 简介 本章节介绍下Mybatis-Plus框架的逻辑删除功能。 📖 正文 1 逻辑删除介绍 1.1 什么是逻辑删除? 首先我们先来了解下与逻辑删除对应…

面试八股——Redis——分布式锁——Redisson

1.看门狗机制 注意看门狗机制:redisson会监听持有锁的线程,并每隔一段时间(releaseTime/3,默认releaseTime为30s),如果线程还未释放锁的话,会给锁做一次续期。 2. 主从一致性 实际开发中我们会搭建多台redis服务器&a…

pytest+yaml+allure接口自动化测试框架

前言# 现在是2024年,自动化测试,是目前测试行业一项比较普遍的测试技术了,之前的以UI自动化测试为主,现在的以接口自动化测试为主,无论技术更迭,自动化测试总有他的重量,用机器代替手工工作&am…

C语言 青蛙跳台阶问题

1.问题描述 一只青蛙可以一次跳一级台阶,也可以一次跳两级台阶,如果青蛙要跳上n级台阶有多少种跳法? 2.问题分析 当台阶只有一级时,只能跳一级,所以只有一种跳法 当台阶有两级时,可以先跳一级&#xff…

【Flutter学习笔记】10.3 组合实例:TurnBox

参考资料:《Flutter实战第二版》 10.3 组合实例:TurnBox 这里尝试实现一个更为复杂的例子,其能够旋转子组件。Flutter中的RotatedBox可以旋转子组件,但是它有两个缺点: 一是只能将其子节点以90度的倍数旋转二是当旋转…

分治归并问题

“别让自我被拯救~” 谈谈归并与分治 当我们首次接触排序算法时,一定对所谓 "归并"方式排序的算法感到头疼~ 因为,我们难以形象出其不断 "分离"时,各个区域的状态。然而,即便 "归并"排序算法的学习…

哪些行业需要在线制作电子证书系统?

哪些行业需要在线制作电子证书系统? 1、教育机构:学校和培训机构需要为学生和培训者颁发证书,您的系统可以帮助他们快速生成和管理这些证书。 2、企业及政府部门:用于员工培训、资质认证等,提高内部管理效率。 3、专…

【C++】虚拟继承 组合

目录 一、虚拟继承 🌟【非虚拟内存分布】 🌟【虚拟继承内存分布】 🌟【虚拟继承读取】 🌟【练习检验】 🌟【继承的总结和反思】 二、组合 🌟【继承和组合】 🌟【前言回顾】 上一篇文章我们…

GL-15过流继电器 10A、5A 板前接线带附件 JOSEF约瑟

系列型号: GL-11过流继电器; GL-12过流继电器; GL-13过流继电器; GL-14过流继电器; GL-15过流继电器; GL-16过流继电器; GL-17过流继电器; 用途 GL-10系列过流继电器(以下简称继电器)具有反时限特性,应用于电机、变压器等主设备以及输配电系统的继电保…

PLC_博图系列☞P:扫描操作数的信号上升沿

PLC_博图系列☞P:扫描操作数的信号上升沿 文章目录 PLC_博图系列☞P:扫描操作数的信号上升沿背景介绍P:扫描操作数的信号上升沿说明参数示例 关键字: PLC、 西门子、 博图、 Siemens 、 p 背景介绍 这是一篇关于PLC编程的文章…

QT_day3:2024/3/22

作业1:设计界面 使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin…

穿越地心:3D可视化技术带你领略地球内部奇观

在广袤无垠的宇宙中,地球是一颗充满生机与奥秘的蓝色星球。我们每天都生活在这颗星球上,感受着它的温暖与恩赐,却往往忽略了它深邃的内部世界。 想象一下,你能够穿越时空,深入地球的核心,亲眼目睹那些亿万年…

面向低成本巡线机器人的PID控制器优化——文末源码

目录 介绍 测试 电子元器件 系统特征 控制器设计 位置误差的计算 比例控制 积分控制 微分控制 改进的PID控制器 测试轨迹 源码链接 本文对经典PID控制器的改进和开环控制机制的发展进行了讨论,以提高差动轮式机器人的稳定性和鲁棒性。为了部署该算法&am…

桌面显示器PD芯片:引领桌面显示技术的新篇章

随着科技的飞速发展,桌面显示器作为人们日常工作与生活中不可或缺的重要设备,其性能与品质也在不断提升。其中,PD芯片作为桌面显示器中的核心组件,发挥着至关重要的作用。本文将对桌面显示器PD芯片进行详细介绍,探讨其…

【排序算法】插入排序与选择排序详解

文章目录 📝选择排序是什么?🌠选择排序思路🌉 直接选择排序🌠选择排序优化🌠优化方法🌉排序优化后问题 🌠选择排序效率特性 🌉插入排序🌠插入排序实现 &#…

总结虚函数表机制——c++多态底层原理

前言: 前几天学了多态。 然后过去几天一直在测试多态的底层与机制。今天将多态的机制以及它的本质分享给受多态性质困扰的友友们。 本节内容只涉及多态的原理, 也就是那张虚表的规则,有点偏向底层。 本节不谈语法!不谈语法&#x…

每日一题|djwcb【算法赛】|字符串快速幂

每日一题|djwcb【算法赛】 djwcb 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 djwcb 注意: 快速幂字符串,看…

js获取cookie

js获取cookie 前言实现讲解特别注意: 前言 主要是通过document.cookie来进行实现的 实现讲解 首先通过document.cookie 来获取到所有的cookie 然后通过分号进行分割成list 然后循环list,将list中的字符串通过首个等号进行分割然后和指定的cookie名进行比对然后返…

Android 导航方式切换

1.导航栏样式目前有,三键导航,也有全局手势导航,具体的设置是在setting里 setting里对应的 代码逻辑在packages\apps\Settings\src\com\android\settings\gestures\SystemNavigationPreferenceController.java static boolean isOverlayPacka…

芯片设计工程师必备基本功——《Verilog+HDL应用程序设计实例精讲》

进入芯片行业需要学习哪些基本功呢?其实芯片设计工程师的技能是通过多年的经验学习的。在您开始作为芯片设计工程师工作之前,很难给出一个需要的全面的单一列表,也不可能学习所有内容。话虽如此,但您开始芯片设计师职业生涯时必须…