好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ES6+ 迭代协议

ES6+ 迭代协议

1. 前言

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

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

2. 可迭代协议和迭代器协议

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

2.1 可迭代协议

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

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

2.2 迭代器协议

上面说到了在实现 Symbol.i tera tor 方法 时需要返回 一个 满足迭代器协议的 方法 。那么迭代器协议又是什么呢?

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

done 是 一个 boolean,在没有迭代完时返回 false,迭代完成后返回 true; value 就是被迭代的返回值,当 done 为 true 时可以省略。

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

3. 迭代器

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

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

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

根据上面的 代码 ,我们可以显式的手动 调用 next() :

  var  i tera tor  =  obj [ Symbol . i tera tor ]  (  )  ; 
 var  s  =  i tera tor .  next  (  )  ; 

 while  (  ! s . done )   { 
  console .  log  ( s . value )  ; 
  s  =  i tera tor .  next  (  )  ; 
 } 
 // 1 
 // 2 
 // ... 
 

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

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

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

4. 小结

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

插入案例

查看更多关于ES6+ 迭代协议的详细内容...

  阅读:43次

上一篇

下一篇

第1节:ES6+ 简介    第2节:ES6 环境配置    第3节:ES6+ let    第4节:ES6+ const    第5节:ES6+ 展开语法    第6节:ES6+ 剩余参数    第7节:ES6+ 解构赋值    第8节:ES6+ 模版字符串    第9节:ES6+ 箭头函数    第10节:ES6+ 数值扩展    第11节:ES6+ isFinite()&isNaN()    第12节:ES6+ Number 对象的方法    第13节:ES6+ Math 对象的扩展    第14节:ES6+ includes()    第15节:ES6+ 字符串的扩展    第16节:ES6+ startsWith()    第17节:ES6+ endsWith()    第18节:ES6+ repeat()    第19节:ES6+ padStart()    第20节:ES6+ padEnd()    第21节:ES6+ trim()    第22节:ES6+ Array.from()    第23节:ES6+ of()    第24节:ES6+ find()和findIndex()    第25节:ES6+ copyWithin()    第26节:ES6+ fill()    第27节:ES6+ isArray()    第28节:ES6+ 对象的扩展    第29节:ES6+ flat()    第30节:ES6+ 可选链操作符    第31节:ES6+ Object.is()    第32节:ES6+ Object.assign()    第33节:ES6+ Object.keys()    第34节:ES6+ Object.values()    第35节:ES6+ Object.entries()    第36节:ES6+ 数据结构扩展    第37节:ES6+ Set    第38节:ES6+ WeakSet    第39节:ES6+ Map    第40节:ES6+ WeakMap    第41节:ES6+ Symbol    第42节:ES6+ for...of    第43节:ES6+ 迭代协议    第44节:ES6+ 实现一个简版的 Promise    第45节:ES6+ Promise 基础    第46节:ES6+ Promise 进阶    第47节:ES6+ Generator 基础    第48节:ES6+ Generator 函数应用    第49节:ES6+ async/await    第50节:ES6+ Class 前置知识    第51节:ES6+ Class    第52节:ES6+ Proxy    第53节:ES6+ Reflect(一)    第54节:ES6+ Reflect(二)    第55节:ES6+ 模块化(一)    第56节:ES6+ 模块化(二)    第57节:ES6实战1-实现Vue3 reactive 源码    第58节:ES6实战2-实现 Vue3 effect 源码    第59节:ES6 实战2-封装请求    第60节:ES6+ 实战3-代码整洁之道    第61节:ES6 Map原理分析    第62节:ES6module语法加载importexport    第63节:ES6的循环与可迭代对象示例详解