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 相关文章推荐
ExtJs之带图片的下拉列表框插件
Mar 04 Javascript
jquery 学习之一 对象访问
Nov 23 Javascript
JS实现的简洁纵向滑动菜单(滑动门)效果
Oct 19 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
Sep 17 Javascript
详解react-webpack2-热模块替换[HMR]
Aug 03 Javascript
浅谈angular.copy() 深拷贝
Sep 14 Javascript
Vue-router 类似Vuex实现组件化开发的示例
Sep 15 Javascript
微信小程序 功能函数小结(手机号验证*、密码验证*、获取验证码*)
Dec 08 Javascript
JS实现字符串翻转的方法分析
Aug 31 Javascript
elementUI 设置input的只读或禁用的方法
Oct 30 Javascript
跨域请求两种方法 jsonp和cors的实现
Nov 11 Javascript
vuecli项目构建SSR服务端渲染的实现
Oct 30 Javascript
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
用Php实现链结人气统计
2006/10/09 PHP
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
PHP缩略图等比例无损压缩,可填充空白区域补充色
2011/06/10 PHP
PHP利用超级全局变量$_POST来接收表单数据的实例
2016/11/05 PHP
thinkPHP5框架auth权限控制类与用法示例
2018/06/12 PHP
Laravel用户授权系统的使用方法示例
2018/09/16 PHP
javascript document.execCommand() 常用解析
2009/12/14 Javascript
常见JS效果之图片减速度滚动实现代码
2011/12/08 Javascript
使用JavaScript刷新网页的方法
2015/06/04 Javascript
JavaScript中的slice()方法使用详解
2015/06/06 Javascript
Jquery实现遮罩层的方法
2015/06/08 Javascript
更高效的使用JQuery 这里总结了8个小技巧
2016/04/13 Javascript
利用Javascript仿Excel的数据透视分析功能
2016/09/07 Javascript
微信小程序学习(4)-系统配置app.json详解
2017/01/12 Javascript
vue.js开发环境安装教程
2017/03/17 Javascript
JavaScript之面向对象_动力节点Java学院整理
2017/06/29 Javascript
React如何利用相对于根目录进行引用组件详解
2017/10/09 Javascript
解决layui页面按钮点击无反应,也不报错的问题
2019/09/29 Javascript
vue 实现tab切换保持数据状态
2020/07/21 Javascript
python实现应用程序在右键菜单中添加打开方式功能
2017/01/09 Python
Windows平台Python连接sqlite3数据库的方法分析
2017/07/12 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
django之静态文件 django 2.0 在网页中显示图片的例子
2019/07/28 Python
基于python及pytorch中乘法的使用详解
2019/12/27 Python
借助Paramiko通过Python实现linux远程登陆及sftp的操作
2020/03/16 Python
Python 字符串池化的前提
2020/07/03 Python
详解python百行有效代码实现汉诺塔小游戏(简约版)
2020/10/30 Python
车间班长岗位职责
2013/11/30 职场文书
国际贸易专业个人职业生涯规划
2014/02/15 职场文书
幼儿园八一建军节活动方案
2014/08/27 职场文书
环境工程专业毕业生求职信
2014/09/30 职场文书
2014年乡镇人大工作总结
2014/11/25 职场文书
公司内部升职自荐信
2015/03/27 职场文书
OpenCV-Python实现油画效果的实例
2021/06/08 Python
Python机器学习应用之基于线性判别模型的分类篇详解
2022/01/18 Python
Android Studio实现简易进制转换计算器
2022/05/20 Java/Android