迭代器与生成器

382 阅读7分钟

前言

本文是ES6的相关知识,虽然知识有点老,我作为一个初学者得要学啊!大家一起共勉!!!加油!

字面量加强

字面量

literal
一种直观的,可以直接写出来的,所见即所得的(12345、true、false、null、[1, 2, 3, 4]...)

原有字面量加强

更安全字面量(0b1111101)

MDN的数字和日期
ES5和ES6对比

  1. 八进制 (0o767)
    0777 (ES5)

    截屏2021-10-16 上午9.44.31.png
    0o777 (ES6)
    截屏2021-10-16 上午9.46.41.png
    八进制中的0888 截屏2021-10-16 上午9.50.24.png
    在ES6中八进制加0o,如果写成了十进制的就会入上图所示,固这种写法更加安全

  2. 二进制就是加 0b使得更加安全(0b1111101)

字符串支持 Unicode

阮一峰写的Unicode与JavaScript详解

截屏2021-10-16 上午10.37.08.png

Symbol 和迭代器

JavaScript目前常见的共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。

截屏2021-10-16 上午11.13.31.png

Symbol 创造一个独一无二的值

截屏2021-10-16 上午11.17.47.png

对象属性加强

  • 属性定义支持短语法 obj = { x, y }
  • 属性名支持表达式 obj = {["baz" + quux() ]: 42}
  • 添加 __proto__ 属性,但不建议使用

迭代

遍历就是一个一个访问
迭代:比如说Vue2 => Vue3 ,LOL的版本1.1=>2.2=>...=>11.2,那升级就是迭代喽 遍历与迭代有啥区别呢?
遍历是已知的有限的数据集,迭代未知,我们永远不知道LOL会升级到多少版本 \

截屏2021-10-16 上午11.37.10.png
如上图所示,一个东西你每一次调它就会返回下一个版本 ,这就是迭代,接下来深入理解
next的意思是下一个版本的入口,done我有没有下一个版本

截屏2021-10-16 下午1.52.55.png
在变

截屏2021-10-16 下午2.01.41.png

截屏2021-10-16 下午2.05.00.png
加上done \

截屏2021-10-16 下午2.22.16.png

截屏2021-10-16 下午2.22.31.png
迭代器可以让你每一次都问我有没有下一个版本有没有下一个版本,如果没有我就给你一个done,如果我已经done了,你还问我。 \

总结

那么迭代器就是一个东西,它有一个 next api, 这个api会返回一个value和一个done,value表示它的值,done表示它有没有结束,如果没有结束每次都会给我一个新的value,如果结束了就会给我们一个done 是 true

生成器 & for...of

首先将以上代码改写成

function* 发布器() {
  var version = 0
  while(true){
    version += 1
    yield version
  }
}

运行一下
截屏2021-10-16 下午9.23.01.png

function* 发布器() {
// 下面的代码只会运行一次
  var version = 0
  while(true){
    version += 1
    yield version // 在 yield 这里发生了变化
  }
}

yield 去掉,那么 version 就会出不去, yield 的在这里就是退出来一个值(你出来一哈),运行 next 后,第一次退出来一个 1,第二次退出来一个 2,第三次退出来一个 3...。退出来之后就停在那,直到我在调用下一次 next ,就在继续

截屏2021-10-16 下午9.37.20.png 我们在来看看这段代码

截屏2021-10-16 下午9.47.09.png
上面的代码运行到 version += 1的时候就不在运行(在 yield 的这里它会停下来),它在等着咋们去nextnext 之后它会把 1 退出来,同时它继续执行到后面的,这个时候从true开始,这个 version 是等于2, 在这个时候它会停着它等我继续 yield 的时候,我运行 next ,那么这个循环就被我们活生生的终断了(本来可能一秒钟循环x万多次,现在只要不 .next 它就不会下一次循环,迭代器的语法糖:现在只要 .next 就循环一次),上面的函数没有 return,只需要每次把迭代的值 yield 出来就可以。
说了这么多那它到底有啥用呢???
背就完事了

迭代器和生成器总结

MDN的链接🔗

  1. 迭代器有一个对象它有一个 next 方法,这个 next 方法,只要调一次它就会返回一个 value 调一次就会返回一个 value
  2. 生成器是迭代器生成的语法糖,如果使用生成器,你只需要在这个函数后面加一个 * 号,然后在每一次前面的值加一个 yield ,那么它会自动的帮我生成一个迭代器。
  3. for of 是迭代器访问的语法糖

可迭代对象

MDN给的解释👇 截屏2021-10-16 下午11.02.22.png
以上说的是何意思?先看看数组有没有迭代

截屏2021-10-16 下午11.08.42.png
它说的意思是👇
截屏2021-10-16 下午11.03.55.png
那么 let item of array 是个啥意思?那么这就要再次回到遍历去解释

截屏2021-10-16 下午11.18.03.png
如果我给 array 添加一个属性

截屏2021-10-16 下午11.21.37.png
那么请问,遍历的时候该不该打出 x 的值🤔🤔🤔\

  • 不该?
  • 为啥不该?也就是说它的遍历是我们故意只看数字不看其他的key😳
  • 还有个length 我们故意不看,那我们这还是完整的遍历吗,还是遍历吗?没有把所有的key都看完 来模拟下数组👇

截屏2021-10-16 下午11.30.11.png
我如果要遍历这个对象的话,那么该不该打印出这个 x???

  • 该? 那么依据什么来判定的呢?如果是数字我一定要看它的数字下标,如果不是数组我一定要看它的所有下标?
    那是这样吗????🤔🤔🤔来做个实验
    假如对象和数组是一模一样的呢?那我们把 array 的下标打出来

截屏2021-10-16 下午11.34.59.png
它没有数字下标,那就是说这个对象和这个数组没有区别啊!
现在把这个对象变成数组👇

截屏2021-10-16 下午11.41.00.png
现在他俩一模一样,那也就是说对象和数组没啥不一样的啊!
那么既然它们一模一样,那它们的遍历为啥不一样啊???
回到JS的基本数据类型,数组是一种特殊的对象,那既然这样为啥遍历的时候感觉不一样呢???
是我们对数组这个名词的认识,在语义上我们所认为的数组就是第一项、第二项、第三项、第四项...,我们认为对象就是有很多 keyvalue,同样的如果认为它是一个迭代对象,那么这个迭代对象就会有一个 next 方法,那么可迭代对象呢?有些对象是可以迭代的,比如说数组👇

截屏2021-10-16 下午11.52.10.png
以上的都可遍历,但是只有数组可以迭代,对象不能迭代,那为啥对象不能迭代(基于现在来说不能,想迭代也可以)???🤔
如果一个东西能够被 for of 使用它就是可以迭代的
以前真正的遍历,不管任何对象都可以遍历👇
截屏2021-10-16 下午11.59.06.png
现在的迭代👇 截屏2021-10-16 下午11.57.18.png\

数组和对象的区别

数组和对象是同一个东西,只是理解的对象不同,数组是没有顺序的,只是我们以为有顺序 那它们的本质区别是啥?
它们的 __protype__ ,数组的原型指向的是Array.prototype,对象的原型指向的是Object.prototype,这两个对象的区别不在于内存上在于原型上 Array.prototype 里有pop push属性、Objec.prototypetoString属性。

回到迭代器

那么也就是说只要是对象就可以遍历,只有符合某些特征的对象才能迭代,而数组就自带呢迭代功能

截屏2021-10-17 上午12.27.39.png 以上你返回的东西跟这个对象有的东西没有关系啊=-=,那我们就让其有关系一些\

截屏2021-10-17 上午12.37.27.png 所以为啥数组可以迭代,对象不可以迭代呢?\

  • 因为数组知道如何按顺序去访问,object 不知道如何去访问这些key,不知道是先给 a,还是先给 b,还是 c.

截屏2021-10-17 上午12.41.43.png Symbol引入最初的意义就是为了实现迭代器实现迭代对象,它是一个独一无二的值
JS发现我要实现一个迭代器我得要给一个语法糖,于是它发明了生成器

// MDN中的生成器语法
function* fibonacci() {
  var fn1 = 0;
  var fn2 = 1;
  while (true) {
    var current = fn1;
    fn1 = fn2;
    fn2 = current + fn1;
    var reset = yield current;
    if (reset) {
        fn1 = 0;
        fn2 = 1;
    }
  }
}
// 一个 * 一个 yield

然后想要一些对象默认就可以迭代,于是引入了一个特殊的属性名 Symbol.iterator

var myIterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
}