制作器和迭代器之间的关系

lxf2023-03-17 12:05:02

制作器和迭代器这俩物品平常作为一个网页切图仔,一直都没有用到。感觉就是仅有在求职以前才大会物品。招聘面试通不过几日,再度看这些词一阵恍惚之间。

记忆能力衰退成这个样子么?较大的主要原因一定是用到减少了。之后呢?就是没真正意义上的了解他们。所以我对他们的认识常常会有以下这些:

1. 我经常把迭代器和制作器理解为截然不同的物品。

2. 我经常把for、forEach、map、reducefor of混为一谈

3. 我经常把二维数组、类二维数组称之为可迭代对象

要来要想真正的记得它,增强自己的军械库,一定要搞明白这个东西才可以。

大家首先就是要弄明白哪些for of是干嘛用的。

业务代码的确应用不了,但如果不了解得话,等真到了可以使用的场景下的情况下,又是不是真的可以运用下去,乃至记起来呢?

for of 是干嘛用的

人人都知道一些定义for、forEach、map、reduce这种是能够遍历数组的,for of主要是用于赋值迭代更新对象。如下所示:

const arr = [1, 2, 3]
arr.forEach((item, index) => {
   console.log(item) // 1, 2, 3 
   console.log(index) // 0, 1, 2
})

而巧的是for of还可以遍历数组

for (let key of arr) {
    console.log(key) // 1 2 3
}

将arr改变为const obj = { a: 1, b: 2, c: 3 }时,它们都并没有赋值结果出来。

前者并没有反映,后面一种就会直接出错:TypeError: obj is not iterable。翻译一下,种类不正确:obj 不是一个可迭代对象。

那么什么是可迭代对象呢?

可迭代对象是啥?

先来看看下面的事例:

const itemLi1 = document.getElementByTagName('li')
const itemLi2 = document.querySelectorAll('li')

for(let key of itemLi1) {
    console.log(item)
}
for(let key of itemLi2) {
    console.log(item)
}

换句话说HTMLCollectionNodeList是能够迭代更新目标。其它的可迭代对象有Array、map、set、string这些。假如说类二维数组得话,是否迭代更新目标呢?

const arrLike = {
  0: 1,
  1: 2,
  2: 3,
  lenght: 3
}
for (let i = 0; i < arrLike.length; i  ) {
    console.log(arrLike[i]) // 1, 2, 3
}
for (let of arrLike) {
    console.log(key) // uncachh TypeError: obj is not iterable
}

for循环打印出了相对应的结论,而for of 出错了。类二维数组并不是可迭代的目标。这确实是怎么回事?大家将类二维数组和HTMLCollection种类直接打印比较一下。

制作器和迭代器之间的关系

而类二维数组如下所示:

制作器和迭代器之间的关系

他们有一个很明显的不一样,可迭代对象的原型链里面是包含Symbol.iterator的。而这就是让二维数组变为可迭代的主要原因。

换句话说,当目地对象原型链上边包含Symbol.iterator时,它才算是可迭代对象。

目标是混乱的,混乱的东西了当然不能迭代更新

这儿应用到Symbol种类,他在MDN上边的理解就是用以形成全局性唯一的自变量。而可迭代对象是它的使用场景。受它启迪,大家在业务之中,必要时前面来生成一个唯一ID时,再度以前,一般都是创建一个UUID的功能来生成一个唯一ID。Symbol无需这么麻烦,直接用就行了。

由此可见,Array.prototype[Symbol.iterater]这一函数公式封装形式了一些东西,促使for of能将目标元素给直接打印。

换一句话而言,便是Array.prototype[Symbol.iterater] = function() {}的落实生成一个迭代器目标。

换句话说,当Object.prototype也是有[Symbol.iterater]的办法时,for of也可以赋值它呢?我们一起来试试看吧。

Object.ptotoype[Symbol.iterator] = function value() {}

这难道不是制作器的功效么?

制作器和迭代器之间的关系。

ES6帮我提升了一个制作器的函数公式。即然称为制作器,它形成的东西都是迭代器。

表达形式如下所示:

function * generation(iterableObject) {
    for(let i = 0; i < iterableObject; i  ) {
        yield iterableObject[i]
    }
}

*标记和yield关键词构成。

const iterator = generation([1, 2, 3]), 其执行过程如下所示:

  1. iterator.next() ==> { value: 1, done: false }
  2. iterator.next() ==> { value: 2, done: false }
  3. iterator.next() ==> { value: 3, done: false }
  4. iterator.next() ==> { value: undefined, done: true }

到第四次,value为undefined时,done为true(换句话说,当done为true时,value一定为undefined)。所以,yield的功效有两种:

  1. 生成一个值,将这个值封装形式成一个目标,而且这个目标是{ value: .., done: flase/true }这种方式
  2. 慢下来

可以明显的看出,制作器有一个功效,根据next这一插口,能够看见迭代更新的一个过程。

即然说制作器生成了一个迭代器,那是不是说制作器实行后结果就是一个迭代器呢?毕竟是迭代器,自然也就能够被for of给赋值。

for (const key of generation([1, 2, 3]) {
    console.log(key) // 1, 2, 3
}

果真能够。

经典面试题: 自身实现一个next这种插口呢?

上边有了完成思路。通过一个标志符和一个分辨就可以使用ES5来用,如下所示代码片段。

function generation(iterableObj) {
    let nextIndex = 0
    function next() {}
    return {
        next: () => {
            return nextIndex < iterableObj.length
                             ? { value: iterableObj[nextIndex  ], done: false }
                             : { value: undefined, done: true } 
        }
    }
}

当nextIndex下于数组长度时,并没有迭代更新结束。

留意:nextIndex 要先跑nextIndex,再自增。

什么是插口,后台管理给你一个url详细地址,这是网线端口。next是室内设计师让你封装形式的一个方法,通过你的用这种方法来实现上吧yield的两个关键点,因此next()也是一个插口,前面插口。简单来说,一个封装形式好的办法就是一个插口。

让非迭代更新目标也可以用for of 开展赋值

如同第一节常说,Symbol.iterator的办法是迭代器的关键所在。那我们也可以给Object初始化上要方式。即然此方法能让目标变为迭代器,就可以直接使用上边ES5完成next方式的代码片段。

const obj = {
  a: 1,
  b: 2,
  c: 3
}
Object.prototype[Symbol.iterator] = function value() {
  const keys = Object.keys(Object(this))
  let nextIndex = 0

  function next() {
    return nextIndex < keys.length
        ? { value: [keys[nextIndex], obj[keys[nextIndex   ]]], done: false }
        : { value: undefined, done: true }
  }

  return {
    next
  }
}
for (const [key, value] in obj) {
  console.log(key)
}

for循环和for in之间的关系

for循环和for in 看见特别像,其实不过是同用了for这一关键词,它们是JS模块最底层完成的东西了。和forEach、map这种都是基于for循环的API不一样,他们要在通过在for循环之上的。

汇总

  • 制作器generator实行结果就是一个迭代器
  • 制作器能是也是由ES5达到的,并不是根据最底层API
  • 是不是迭代器的关键在于Symbol.iterator方式

“打开AdminJS成长之路!这个是我参加「AdminJS日新的目标 · 2 月更文考验」第 18 天,查看更多活动规则”