ES6 Iterator遍历器原理,应用场景及相关常用知识拓展详解


Posted in Javascript onFebruary 15, 2020

本文实例讲述了ES6 Iterator遍历器原理,应用场景及相关常用知识拓展。分享给大家供大家参考,具体如下:

介绍Iterator之前先列举下js的表示数据集合结构的几种方式:

在es6之前有 Array , Object, es6新增了 map, set,当然用户也可以组合使用这几种数据结构,灵活存储数据。

但是当数据结构变得复杂后,怎样取到里面的数据就也相对复杂,这就需要有一种读取数据的统一的接口机制,来处理不同的数据结构。

遍历器就是这样一种接口机制,Iterator是一种接口,为不同数据结构提供统一的接口机制。

相应的任何数据结构只要部署Iterator接口,就可以完成遍历操作。

Iterator的作用:

1,为各种数据结构提供一种统一的,简单的访问接口;

2,使得数据结构的成员能够按照某种次序排列;

3,ES6提供了一种新的遍历循环(for......of.....),Iterator被for......of.....循环调用;

Iterator本质:

遍历器本质上是一种指针对象,指针对象上有next()方法,第几次调用就指向第几个成员

Iterator上next()方法调用返回:

1,返回当前成员的信息

2,返回遍历是否结束

模拟实现Iterator

var it = makeIterator(['a', 'b']);
 
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
 
function makeIterator(array) {
 var nextIndex = 0;
 return {
  next: function() {
   return nextIndex < array.length ?
    {value: array[nextIndex++], done: false} :
    {value: undefined, done: true};
  }
 };
}

使用Typescript

interface Iterable {
 [Symbol.iterator]() : Iterator,
}
 
interface Iterator {
 next(value?: any) : IterationResult,
}
 
interface IterationResult {
 value: any,
 done: boolean,
}

关于默认的Iterator接口:

ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。

Symbol.iterator的本质:

1,Symbol.iterator本身是一个函数,对应当前数据结构默认的遍历器生成函数;

2,执行Symbol.iterator这个函数会返回一个遍历器。

实例:

const obj = {
 [Symbol.iterator] : function () {
  return {
   next: function () {
    return {
     value: 1,
     done: true
    };
   }
  };
 }
};
//这样定义后对象就有了Iterator接口
//执行对象obj的symbol.iterator后,返回一个遍历器

具有原生iterator的数据结构:

Array , Map, Set, String, TypedArray, 函数的argulements对象,NodeList对象(节点对象);

数组iterator实例

let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
 
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }

对象iterator接口实现

class RangeIterator {
 constructor(start, stop) {
  this.value = start;
  this.stop = stop;
 }
 
 [Symbol.iterator]() { return this; }
 
 next() {
  var value = this.value;
  if (value < this.stop) {
   this.value++;
   return {done: false, value: value};
  }
  return {done: true, value: undefined};
 }
}
 
function range(start, stop) {
 return new RangeIterator(start, stop);
}
 
for (var value of range(0, 3)) {
 console.log(value); // 0, 1, 2
}

注意:如果一个对象没有iterator接口,而其原型链上有Iterator接口,也可以通过继承而拥有该接口;

使用while循环遍历

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
 var x = $result.value;
 // ...
 $result = $iterator.next();
}

基本概念基本就是这些,接下来看下使用场景

Iterator的使用场景:

默认调用场景:

for....of...循环, 解构赋值, 扩展运算符, yield*关键字

ES6 借鉴 C++、Java、C# 和 Python 语言,引入了for...of循环,作为遍历所有数据结构的统一的方法

这里主要介绍下yield*,其余几个都比较好理解

yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口

let generator = function* () {
 yield 1;
 yield* [2,3,4];//执行时默认遍历数组
 yield 5;
};
 
var iterator = generator();
 
iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }

其他场景:

由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口

  • for...of
  • Array.from()
  • Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]])
  • Promise.all()
  • Promise.race()

知识拓展

遍历器对象的 return(),throw()

return方法在循环退出或者报错时调用

throw方法主要是配合 Generator 函数使用(详见generator)

计算生成的数据结构

在原有数据结构基础上计算生成的数据结构,例如Object,Map,Set,Array的entries(),keys(), value()方法生成的数据结构,默认具有iterator接口

类似数组对象

常见:字符串,NodeList节点对象,参数arguments

1,并不是所有类似数组的对象都具有 Iterator 接口

2,对于类数组对象可以通过Array.From()将类数组对象转化为数组对象

3,for-of可以识别32 位 UTF-16 字符

for (let x of 'a\uD83D\uDC0A') {
 console.log(x);
}

for-of和其他遍历方法对比:

for循环,forEach循环,for...in...循环

forEach循环无法中途跳出

for...in循环有几个缺点(for...in循环主要是为遍历对象而设计的,不适用于遍历数组),

  • 数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。
  • for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
  • 某些情况下,for...in循环会以任意顺序遍历键名。

对于for...of...

  • 有着同for...in一样的简洁语法,但是没有for...in那些缺点。
  • 不同于forEach方法,它可以与breakcontinuereturn配合使用。
  • 提供了遍历所有数据结构的统一操作接口。

参考:http://es6.ruanyifeng.com/

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
很棒的学习jQuery的12个网站推荐
Apr 28 Javascript
JavaScript字符串String和Array操作的有趣方法
Dec 18 Javascript
百度地图api应用标注地理位置信息(js版)
Feb 01 Javascript
js中判断用户输入的值是否为空的简单实例
Dec 23 Javascript
jquery中checkbox全选失效的解决方法
Dec 26 Javascript
详解jQuery Mobile自定义标签
Jan 06 Javascript
jQuery实现鼠标跟随提示层效果代码(可显示文本,Div,Table,Html等)
Apr 18 Javascript
使用jQuery5分钟快速搞定双色表格的简单实例
Aug 08 Javascript
JS实现获取当前URL和来源URL的方法
Aug 24 Javascript
如何解决vue2.0下IE浏览器白屏问题
Sep 13 Javascript
vue模块拖拽实现示例代码
Mar 09 Javascript
vue 数据双向绑定的实现方法
Mar 04 Vue.js
es6 super关键字的理解与应用实例分析
Feb 15 #Javascript
es6中class类静态方法,静态属性,实例属性,实例方法的理解与应用分析
Feb 15 #Javascript
Vue父子传递实例讲解
Feb 14 #Javascript
Javascript操作select控件代码实例
Feb 14 #Javascript
微信小程序复选框实现多选一功能过程解析
Feb 14 #Javascript
node.js使用net模块创建服务器和客户端示例【基于TCP协议】
Feb 14 #Javascript
node事件循环和process模块实例分析
Feb 14 #Javascript
You might like
dedecms中显示数字验证码的修改方法
2007/03/21 PHP
PHP导入Excel到MySQL的方法
2011/04/23 PHP
php readfile下载大文件失败的解决方法
2017/05/22 PHP
javascript innerHTML、outerHTML、innerText、outerText的区别
2008/11/24 Javascript
文本框获得焦点和失去焦点的判断代码
2012/03/18 Javascript
Javascript计算两个marker之间的距离(Google Map V3)
2013/04/26 Javascript
jquery 按钮状态效果 正常、移上、按下
2013/08/12 Javascript
JavaScript中的Math.LOG2E属性使用详解
2015/06/14 Javascript
使用AngularJS创建单页应用的编程指引
2015/06/19 Javascript
JS实现CheckBox复选框全选、不选或全不选功能
2020/07/28 Javascript
JS代码实现table数据分页效果
2016/05/26 Javascript
jQuery实现在HTML文档加载完毕后自动执行某个事件的方法
2017/05/08 jQuery
jQuery Pagination分页插件_动力节点Java学院整理
2017/07/17 jQuery
node.js实现的装饰者模式示例
2017/09/06 Javascript
详解webpack编译多页面vue项目的配置问题
2017/12/11 Javascript
Auto.js自动收取自己和好友蚂蚁森林能量脚本
2018/06/28 Javascript
详解浏览器缓存和webpack缓存配置
2018/07/06 Javascript
JS实现select选中option触发事件操作示例
2018/07/13 Javascript
微信小程序--特定区域滚动到顶部时固定的方法
2019/04/28 Javascript
微信小程序结合Storage实现搜索历史效果
2019/05/18 Javascript
基于vue.js实现购物车
2020/01/15 Javascript
解决vue elementUI 使用el-select 时 change事件的触发问题
2020/11/17 Vue.js
vue watch监控对象的简单方法示例
2021/01/07 Vue.js
详解python中xlrd包的安装与处理Excel表格
2016/12/16 Python
python数据封装json格式数据
2018/03/04 Python
Python 3.x 安装opencv+opencv_contrib的操作方法
2018/04/02 Python
使用Pyinstaller转换.py文件为.exe可执行程序过程详解
2019/08/06 Python
python自动化工具之pywinauto实例详解
2019/08/26 Python
使用Keras预训练模型ResNet50进行图像分类方式
2020/05/23 Python
Python库安装速度过慢解决方案
2020/07/14 Python
WebSphere 应用服务器都支持哪些认证
2013/12/26 面试题
人力资源管理专业自荐书
2014/07/07 职场文书
机关作风建设自查报告
2014/10/22 职场文书
2016年小学生新年寄语
2015/08/18 职场文书
电脑开机弹出documents文件夹怎么回事?弹出documents文件夹解决方法
2022/04/08 数码科技
python和anaconda的区别
2022/05/06 Python