ES6 Iterator遍历器原理,应用场景及相关常用知识拓展详解
本文实例讲述了ES6Iterator遍历器原理,应用场景及相关常用知识拓展。分享给大家供大家参考,具体如下:
介绍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
varit=makeIterator(['a','b']);
it.next()//{value:"a",done:false}
it.next()//{value:"b",done:false}
it.next()//{value:undefined,done:true}
functionmakeIterator(array){
varnextIndex=0;
return{
next:function(){
returnnextIndex
使用Typescript
interfaceIterable{
[Symbol.iterator]():Iterator,
}
interfaceIterator{
next(value?:any):IterationResult,
}
interfaceIterationResult{
value:any,
done:boolean,
}
关于默认的Iterator接口:
ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
Symbol.iterator的本质:
1,Symbol.iterator本身是一个函数,对应当前数据结构默认的遍历器生成函数;
2,执行Symbol.iterator这个函数会返回一个遍历器。
实例:
constobj={
[Symbol.iterator]:function(){
return{
next:function(){
return{
value:1,
done:true
};
}
};
}
};
//这样定义后对象就有了Iterator接口
//执行对象obj的symbol.iterator后,返回一个遍历器
具有原生iterator的数据结构:
Array,Map,Set,String,TypedArray,函数的argulements对象,NodeList对象(节点对象);
数组iterator实例
letarr=['a','b','c'];
letiter=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接口实现
classRangeIterator{
constructor(start,stop){
this.value=start;
this.stop=stop;
}
[Symbol.iterator](){returnthis;}
next(){
varvalue=this.value;
if(value
注意:如果一个对象没有iterator接口,而其原型链上有Iterator接口,也可以通过继承而拥有该接口;
使用while循环遍历
var$iterator=ITERABLE[Symbol.iterator]();
var$result=$iterator.next();
while(!$result.done){
varx=$result.value;
//...
$result=$iterator.next();
}
基本概念基本就是这些,接下来看下使用场景
Iterator的使用场景:
默认调用场景:
for....of...循环,解构赋值,扩展运算符,yield*关键字
ES6借鉴C++、Java、C#和Python语言,引入了for...of循环,作为遍历所有数据结构的统一的方法
这里主要介绍下yield*,其余几个都比较好理解
yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口
letgenerator=function*(){
yield1;
yield*[2,3,4];//执行时默认遍历数组
yield5;
};
variterator=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()(比如newMap([['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(letxof'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方法,它可以与break、continue和return配合使用。
- 提供了遍历所有数据结构的统一操作接口。
参考:http://es6.ruanyifeng.com/
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。