当前位置: 首页 > news >正文

45.[前端开发-JavaScript高级]Day10-迭代器-生成器

Iterator-Generator详解

1 迭代器可迭代对象

什么是迭代器?

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>const names = ["abc", "cba", "nba"]// 给数组names创建一个迭代器(迭代器: names的跌大气)let index = 0const namesIterator = {next: function() {// done: Boolean// value: 具体值/undefinedif (index < names.length) {return { done: false, value: names[index++] }} else {return { done: true }}}}console.log(namesIterator.next())console.log(namesIterator.next())console.log(namesIterator.next())console.log(namesIterator.next())// 数组numsconst nums = [100, 24, 55, 66, 86]let indexNum = 0const numsIterator = {next: function() {// done: Boolean// value: 具体值/undefinedif (indexNum < nums.length) {return { done: false, value: nums[indexNum++] }} else {return { done: true }}}}</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>const names = ["abc", "cba", "nba"]const nums = [100, 24, 55, 66, 86]// 封装一个函数function createArrayIterator(arr) {let index = 0return {next: function() {if (index < arr.length) {return { done: false, value: arr[index++] }} else {return { done: true }}}}}const namesIterator = createArrayIterator(names)console.log(namesIterator.next())console.log(namesIterator.next())console.log(namesIterator.next())console.log(namesIterator.next())const numsIterator = createArrayIterator(nums)console.log(numsIterator.next())console.log(numsIterator.next())console.log(numsIterator.next())console.log(numsIterator.next())console.log(numsIterator.next())console.log(numsIterator.next())</script></body>
</html>

迭代器的代码练习

可迭代对象

可迭代对象的代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 将infos变成一个可迭代对象/*1.必须实现一个特定的函数: [Symbol.iterator]2.这个函数需要返回一个迭代器(这个迭代器用于迭代当前的对象)*/const infos = {friends: ["kobe", "james", "curry"],[Symbol.iterator]: function() {let index = 0const infosIterator = {next: function() {// done: Boolean// value: 具体值/undefinedif (index < infos.friends.length) {return { done: false, value: infos.friends[index++] }} else {return { done: true }}}}return infosIterator}}// 给infos创建一个迭代器, 迭代infos中的friends// console.log(infosIterator.next())// console.log(infosIterator.next())// console.log(infosIterator.next())// console.log(infosIterator.next())// 可迭代对象必然具备下面的特点// const iterator = infos[Symbol.iterator]()// console.log(iterator.next())// console.log(iterator.next())// console.log(iterator.next())// console.log(iterator.next())// 可迭对象可以进行for of操作for (const item of infos) {console.log(item)}// 可迭代对象必然有一个[Symbol.iterator]函数// 数组是一个可迭代对象const students = ["张三", "李四", "王五"]console.log(students[Symbol.iterator])const studentIterator = students[Symbol.iterator]()console.log(studentIterator.next())console.log(studentIterator.next())console.log(studentIterator.next())console.log(studentIterator.next())</script></body>
</html>

优化

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 将infos变成一个可迭代对象/*1.必须实现一个特定的函数: [Symbol.iterator]2.这个函数需要返回一个迭代器(这个迭代器用于迭代当前的对象)*/// 1.迭代infos中friends// const infos = {//   friends: ["kobe", "james", "curry"],//   [Symbol.iterator]: function() {//     let index = 0//     const infosIterator = {//       next: () => {//         if (index < this.friends.length) {//           return { done: false, value: this.friends[index++] }//         } else {//           return { done: true }//         }//       }//     }//     return infosIterator//   }// }// 2.迭代infos中的key/valueconst infos = {name: "why",age: 18,height: 1.88,[Symbol.iterator]: function() {// const keys = Object.keys(this)// const values = Object.values(this)const entries = Object.entries(this)let index = 0const iterator = {next: function() {if (index < entries.length) {return { done: false, value: entries[index++] }} else {return { done: true }}}}return iterator}}// 给infos创建一个迭代器, 迭代infos中的friends// console.log(infosIterator.next())// console.log(infosIterator.next())// console.log(infosIterator.next())// console.log(infosIterator.next())// 可迭代对象必然具备下面的特点// const iterator = infos[Symbol.iterator]()// console.log(iterator.next())// console.log(iterator.next())// console.log(iterator.next())// console.log(iterator.next())// 可迭对象可以进行for of操作for (const item of infos) {const [key, value] = itemconsole.log(key, value)}</script></body>
</html>

2 原生的迭代器对象

原生迭代器对象

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 1.数组// const names = ["abc", "cba", "nba"]// for (const name of names) {//   console.log(name)// }// console.log(names[Symbol.iterator]())// 2.Set// const set = new Set(["abc", "cba", "nba"])// for (const item of set) {//   console.log(item)// }// const setIterator = set[Symbol.iterator]()// console.log(setIterator.next())// console.log(setIterator.next())// console.log(setIterator.next())// console.log(setIterator.next())// 3.argumentsfunction foo() {for (const arg of arguments) {console.log(arg)}}foo(123, 321, 111, 222)</script></body>
</html>

可迭代对象的应用

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 1.用在特定的语法上const names = ["abc", "cba", "nba"]const info = {name: "why",age: 18,height: 1.88,[Symbol.iterator]: function() {const values = Object.values(this)let index = 0const iterator = {next: function() {if (index < values.length) {return { done: false, value: values[index++] }} else {return { done: true }}}}return iterator}}function foo(arg1, arg2, arg3) {console.log(arg1, arg2, arg3)}foo(...info)// 2.一些类的构造方法中, 也是传入的可迭代对象const set = new Set(["aaa", "bbb", "ccc"])const set2 = new Set("abc")console.log(set2)const set3 = new Set(info)console.log(set3)// 3.一些常用的方法const p1 = Promise.resolve("aaaa")const p2 = Promise.resolve("aaaa")const p3 = Promise.resolve("aaaa")const pSet = new Set()pSet.add(p1)pSet.add(p2)pSet.add(p3)Promise.all(pSet).then(res => {console.log("res:", res)})function bar() {// console.log(arguments)// 将arguments转成Array类型const arr = Array.from(arguments)console.log(arr)}bar(111, 222, 333)</script></body>
</html>

3 自定义类的迭代器

自定义类的迭代

自定义类的迭代实现

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>class Person {constructor(name, age, height, friends) {this.name = namethis.age = agethis.height = heightthis.friends = friends}// 实例方法running() {}[Symbol.iterator]() {let index = 0const iterator = {next: () => {if (index < this.friends.length) {return { done: false, value: this.friends[index++] }} else {return { done: true }}}}return iterator}}const p1 = new Person("why", 18, 1.88, ["curry", "kobe", "james", "tatumu"])const p2 = new Person("kobe", 30, 1.98, ["curry", "james", "aonier", "weide"])for (const item of p2) {console.log(item)}</script></body>
</html>

迭代器的中断

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>class Person {constructor(name, age, height, friends) {this.name = namethis.age = agethis.height = heightthis.friends = friends}// 实例方法running() {}[Symbol.iterator]() {let index = 0const iterator = {next: () => {if (index < this.friends.length) {return { done: false, value: this.friends[index++] }} else {return { done: true }}},return: () => {console.log("监听到迭代器中断了")return { done: true }}}return iterator}}const p1 = new Person("why", 18, 1.88, ["curry", "kobe", "james", "tatumu"])for (const item of p1) {console.log(item)if (item === "kobe") {break}}</script></body>
</html>

4 生成器理解和作用

什么是生成器?

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>/*生成器函数: 1.function后面会跟上符号: *2.代码的执行可以被yield控制3.生成器函数默认在执行时, 返回一个生成器对象* 要想执行函数内部的代码, 需要生成器对象, 调用它的next操作* 当遇到yield时, 就会中断执行*/// 1.定义了一个生成器函数function* foo() {console.log("1111")console.log("2222")yieldconsole.log("3333")console.log("4444")yieldconsole.log("5555")console.log("6666")}// 2.调用生成器函数, 返回一个 生成器对象const generator = foo()// 调用next方法generator.next()generator.next()generator.next()</script></body>
</html>

生成器函数执行

生成器传递参数 – next函数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// const names = ["abc", "cba", "nba"]// const iterator = names[Symbol.iterator]()// console.log(iterator.next())/*生成器函数: 1.function后面会跟上符号: *2.代码的执行可以被yield控制3.生成器函数默认在执行时, 返回一个生成器对象* 要想执行函数内部的代码, 需要生成器对象, 调用它的next操作* 当遇到yield时, 就会中断执行*/// 1.定义了一个生成器函数function* foo(name1) {console.log("执行内部代码:1111", name1)console.log("执行内部代码:2222", name1)const name2 = yield "aaaa"console.log("执行内部代码:3333", name2)console.log("执行内部代码:4444", name2)const name3 = yield "bbbb"// return "bbbb"console.log("执行内部代码:5555", name3)console.log("执行内部代码:6666", name3)yield "cccc"return undefined}// 2.调用生成器函数, 返回一个 生成器对象const generator = foo("next1")// 调用next方法// console.log(generator.next()) // { done: false, value: "aaaa" }// console.log(generator.next()) // { done: false, value: "bbbb" }// console.log(generator.next()) //  { done: false, value: "cccc" }// console.log(generator.next()) // {done: true, value: undefined}// 3.在中间位置直接return, 结果// console.log(generator.next()) // { done: false, value: "aaaa" }// console.log(generator.next()) // { done: true, value: "bbbb" }// console.log(generator.next()) // { done: true, value: undefined }// console.log(generator.next()) // { done: true, value: undefined }// console.log(generator.next()) // { done: true, value: undefined }// console.log(generator.next()) // { done: true, value: undefined }// 4.给函数每次执行的时候, 传入参数console.log(generator.next())console.log(generator.next("next2"))console.log(generator.next("next3"))// console.log(generator.next())</script></body>
</html>

生成器提前结束 – return函数

生成器抛出异常 – throw函数

生成器替代迭代器

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 1.对之前的代码进行重构(用生成器函数)const names = ["abc", "cba", "nba"]const nums = [100, 22, 66, 88, 55]function* createArrayIterator(arr) {for (let i = 0; i < arr.length; i++) {yield arr[i]}// yield arr[0]// yield arr[1]// yield arr[2]// return undefined}// const namesIterator = createArrayIterator(names)// console.log(namesIterator.next())// console.log(namesIterator.next())// console.log(namesIterator.next())// console.log(namesIterator.next())// const numsIterator = createArrayIterator(nums)// console.log(numsIterator.next())// console.log(numsIterator.next())// console.log(numsIterator.next())// console.log(numsIterator.next())// console.log(numsIterator.next())// console.log(numsIterator.next())// 2.生成器函数, 可以生成某个范围的值// [3, 9)function* createRangeGenerator(start, end) {for (let i = start; i < end; i++) {yield i}}const rangeGen = createRangeGenerator(3, 9)console.log(rangeGen.next())console.log(rangeGen.next())console.log(rangeGen.next())console.log(rangeGen.next())console.log(rangeGen.next())console.log(rangeGen.next())console.log(rangeGen.next())console.log(rangeGen.next())</script></body>
</html>

5 自定义生成器方案

自定义类迭代 – 生成器实现

对生成器的操作

6 异步处理方案解析

异步处理方案

Generator方案

自动执行generator函数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 封装请求的方法: url -> promise(result)function requestData(url) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(url)}, 2000)})}// 1.发送一次网络请求// requestData("http://why").then(res => {//   console.log("res:", res)// })/*需求: 1.发送一次网络请求, 等到这次网络请求的结果2.发送第二次网络请求, 等待这次网络请求的结果3.发送第三次网络请求, 等待这次网络请求的结果*/// 方式一: 层层嵌套(回调地狱 callback hell)// function getData() {//   // 1.第一次请求//   requestData("why").then(res1 => {//     console.log("第一次结果:", res1)//     // 2.第二次请求//     requestData(res1 + "kobe").then(res2 => {//       console.log("第二次结果:", res2)//       // 3.第三次请求//       requestData(res2 + "james").then(res3 => {//         console.log("第三次结果:", res3)//       })//     })//   })// }// 方式二: 使用Promise进行重构(解决回调地狱)// 链式调用// function getData() {//   requestData("why").then(res1 => {//     console.log("第一次结果:", res1)//     return requestData(res1 + "kobe")//   }).then(res2 => {//     console.log("第二次结果:", res2)//     return requestData(res2 + "james")//   }).then(res3 => {//     console.log("第三次结果:", res3)//   })// }// 方式三: 最终代码// function* getData() {//   const res1 = yield requestData("why")//   console.log("res1:", res1)//   const res2 = yield requestData(res1 + "kobe")//   console.log("res2:", res2)//   const res3 = yield requestData(res2 + "james")//   console.log("res3:", res3)// }// const generator = getData()// generator.next().value.then(res1 => {//   generator.next(res1).value.then(res2 => {//     generator.next(res2).value.then(res3 => {//       generator.next(res3)//     })//   })// })// 方式四: async/await的解决方案async function getData() {const res1 = await requestData("why")console.log("res1:", res1)const res2 = await requestData(res1 + "kobe")console.log("res2:", res2)const res3 = await requestData(res2 + "james")console.log("res3:", res3)}const generator = getData()</script></body>
</html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>// 封装请求的方法: url -> promise(result)function requestData(url) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(url)}, 2000)})}// 生成器的处理方案function* getData() {const res1 = yield requestData("why")console.log("res1:", res1)const res2 = yield requestData(res1 + "kobe")console.log("res2:", res2)const res3 = yield requestData(res2 + "james")console.log("res3:", res3)const res4 = yield requestData(res3 + "curry")console.log("res4:", res4)const res5 = yield requestData(res4 + "tatumu")console.log("res5:", res5)}// const generator = getData()// generator.next().value.then(res1 => {//   generator.next(res1).value.then(res2 => {//     generator.next(res2).value.then(res3 => {//       generator.next(res3).value.then(res4 => {//         generator.next(res4)//       })//     })//   })// })// 自动化执行生成器函数(了解)function execGenFn(genFn) {// 1.获取对应函数的generatorconst generator = genFn()// 2.定义一个递归函数function exec(res) {// result -> { done: true/false, value: 值/undefined }const result = generator.next(res)if (result.done) returnresult.value.then(res => {exec(res)})}// 3.执行递归函数exec()}execGenFn(getData)</script></body>
</html>

相关文章:

  • Git创建空分支并推送到远程仓库
  • 市场分析 3 mysql (槽)
  • YOLO11改进,尺度动态损失函数Scale-based Dynamic Loss,减少标签不准确对损失函数稳定性的影响
  • 【网络安全】OWASP 十大漏洞
  • 蓝桥杯2024省A.成绩统计
  • 组件是怎样写的(1):虚拟列表-VirtualList
  • Activity之间交互
  • spark与hadoop的区别
  • Flutter 状态管理 Riverpod
  • 【Linux】多线程任务模块
  • 【Linux篇】轻松搭建命名管道通信:客户端与服务器的互动无缝连接
  • 卷积神经网络--手写数字识别
  • day33和day34图像处理OpenCV
  • 教育行业网络安全:守护学校终端安全,筑牢教育行业网络安全防线!
  • FastGPT Docker Compose本地部署与硅基流动免费AI接口集成指南
  • 【计算机网络】第五章 局域网技术
  • GPT,Genini, Claude Llama, DeepSeek,Qwen,Grok,选对LLM大模型真的可以事半功倍!
  • 形象理解华为云物联网iotDA开发流程
  • 批量导出多个文件和文件夹名称与路径信息到Excel表格的详细方法
  • AgentGPT开源程序可以在浏览器中组装、配置和部署自主人工智能代理
  • 深一度|中国花样滑冰因何大滑坡
  • 延安市委副书记马月逢已任榆林市委副书记、市政府党组书记
  • 竹子砍了地却种不上,贵州赤水被指“整改复耕”存形式主义
  • 一周人物| 萨韦利上海画展,陆永安“从董源到塞尚”
  • 北京理工大学解除宫某聘用关系,该教师被指涉嫌骚扰猥亵学生
  • 解读丨连续两日施压,特朗普为何着急让美联储降息