您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

ES6+ 迭代协议

上一节我们对 ES6 新增的 for...of 做了深入的讲解,它可以用于字符串、数组、类数组、以及新增的数据结构 Map/Set 等进行遍历。但是这些能够使用 for...of 进行遍历的都有共同的特性 —— 可迭代。那什么是可迭代呢?

ECMAScript 2015 在一组补充规范中规定了两个协议:可迭代协议和迭代器协议。这两个规定不是新的内置实现或语法,而是协议。这些协议可以被任何数据结构遵循,从而可以实现的遍历,而这些遵守迭代协议的数据结构是可以被 for...of 遍历的。有了这样的规范,我们所定义的数据结构就会更加丰富了,本节我们将深入 ES6 中的迭代。

迭代协议两方面的 —— 可迭代协议和迭代器协议,下面我们就来看看这两个协议都是什么。

什么是可迭代协议?可以通过 JavaScript 对象定义或定制迭代行为,在 JavaScript 中有一些内置类型并且满足内置的可迭代对象,具有迭代的行为。如 Array、Map、Set 等。还有比如字面量对象(Object)则没有,如果要对 Object 进行迭代的话需要使用 for...in 循环,但是 for...in 在循环时需要判断是否是自身。所以很多时候如果想用 for...of 进行迭代时就需要使用对象上的 Object.keys() 等对象中的 keys 后再去进行遍历操作。

在 ES6 中可迭代协议规定想要成为可迭代对象,这个对象必须实现 @@iterator 。这意味着对象(或者它原型链上的某个对象)必须有键为 @@iterator 的,可通过常量 Symbol.iterator 访问该。所以,对象满足可迭代协议的关键在于实现 Symbol.iterator ,这个的返回值是符合迭代器协议的对象,并且是无参数的。

上面说到了在实现 Symbol.iterator 时需要返回满足迭代器协议的。那么迭代器协议又是什么呢?

迭代器协议定义了产生一系列值的标准方式,迭起协议规定需要返回带 next() 的对象。 next() 可以被多次执行,每次执行都会返回对象,该对象包含两个,donevalue:

实现了以上两点才会满足迭代器协议。一般来说可迭代协议和迭代器协议在实际的场景中是的。下面我来看看什么是迭代器?并且怎么使用可迭代协议和迭代协议去实现迭代器。

这里说的迭代器是遵循上面两个协议来实现的,在满足两个协议时,我们可以显式地通过不断 next () 去进行迭代。在迭代迭代器后,我们称之为消耗了这个迭代器而,且每个迭代器只能执行一次。下面我们来看看怎么实现迭代器:

var@H__112@ obj =@H__112@ {@H__112@}@H__112@
obj[@H__112@Symbol.@H__112@iterator]@H__112@ =@H__112@ function@H__112@(@H__112@)@H__112@ {@H__112@
  let@H__112@ index =@H__112@ ;@H__112@
  return@H__112@ {@H__112@
    next@H__112@(@H__112@)@H__112@ {@H__112@
      if@H__112@ (@H__112@index <=@H__112@ )@H__112@ {@H__112@
        return@H__112@ {@H__112@value:@H__112@ index++@H__112@,@H__112@ done:@H__112@ false@H__112@}@H__112@
      }@H__112@ else@H__112@ {@H__112@
        return@H__112@ {@H__112@done:@H__112@ true@H__112@}@H__112@
      }@H__112@
    }@H__112@
  }@H__112@
}@H__112@

上面的中根据可迭代协议给 obj 对象 Symbol.iterator ,再根据迭代器协议返回 next() ,在每次消耗 next() 时对 index 进行加 1 操作。当 index 大于 10 的时候结束迭代行为,之后再消耗 next() 返回值不变。

根据上面的,我们可以显式的手动 next()

var@H__112@ iterator =@H__112@ obj[@H__112@Symbol.@H__112@iterator]@H__112@(@H__112@)@H__112@;@H__112@
var@H__112@ s =@H__112@ iterator.@H__112@next@H__112@(@H__112@)@H__112@;@H__112@

while@H__112@(@H__112@!@H__112@s.@H__112@done)@H__112@ {@H__112@
  console.@H__112@log@H__112@(@H__112@s.@H__112@value)@H__112@;@H__112@
  s =@H__112@ iterator.@H__112@next@H__112@(@H__112@)@H__112@;@H__112@
}@H__112@
// 1@H__112@
// 2@H__112@
// ...@H__112@

执行上面的,在浏览器的控制台中,可以看到大于的结果是 1 到 10。上面是我们手动执行消耗 next() 的方式,上面我们也说了,只要满足迭代协议就可以被 for...of 循环,那是不是真的是这样的呢?下面我们就使用 for...of 对 obj 进行循环。

for@H__112@ (@H__112@let@H__112@ i of@H__112@ obj)@H__112@ {@H__112@
  console.@H__112@log@H__112@(@H__112@i)@H__112@
}@H__112@
// 1@H__112@
// 2@H__112@
// ...@H__112@

在控制台中执行上面的,可以看到和我们使用手动 next() 方式返回打印的结果是一样的。

本节我们主要学习了两个协议 —— 可迭代协议和迭代器协议,并且通过这两个协议实现了迭代器。通过这个迭代器我们知道,在满足这两个协议后就可以使用 for...of 进行循环,并且我们进行进行了验证。

插入案例


联系我
置顶