本文实例讲述了ES6 Iterator遍历器原理,应用场景及相关常用知识拓展。分享给大家供大家参考,具体如下:介绍Iterator之前先列举下js的表示数据集合结构的几种方式:在es6之前有 Array , Object, es6新增了 map, set,当然用户也可以组合使用这几种数据结构,灵活存储数据。但是当数据结构变得复杂后,怎样取到里面的数据就也相对复杂,这就需要有一种读取数据的统一的接口机制,来处理不同的数据结构。遍历器就是这样一种接口机制,Iterator是一种接口,为不同数据结构提供统一的接口机制。遍历器就是这样一种接口机制,Iterator是一种接口,为不同数据结构提供统一的接口机制。相应的任何数据结构只要部署Iterator接口,就可以完成遍历操作。相应的任何数据结构只要部署Iterator接口,就可以完成遍历操作。Iterator的作用:1,为各种数据结构提供一种统一的,简单的访问接口;2,使得数据结构的成员能够按照某种次序排列;3,ES6提供了一种新的遍历循环(for......of.....),Iterator被for......of.....循环调用;Iterator本质:遍历器本质上是一种指针对象,指针对象上有next()方法,第几次调用就指向第几个成员Iterator上next()方法调用返回:1,返回当前成员的信息2,返回遍历是否结束模拟实现Iterator模拟实现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};

}
};
}

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,
}

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.iteratorSymbol.iteratorSymbol.iterator的本质:1,Symbol.iterator本身是一个函数,对应当前数据结构默认的遍历器生成函数;2,执行Symbol.iterator这个函数会返回一个遍历器。实例:
const obj = {
[Symbol.iterator] : function () {

return {

next: function () {

return {

value: 1,

done: true

};

}

};
}
};
//这样定义后对象就有了Iterator接口
//执行对象obj的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对象(节点对象);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 }

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
}

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循环遍历使用while循环遍历while
var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
var x = $result.value;
// ...
$result = $iterator.next();
}

var $iterator = ITERABLE[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
var x = $result.value;
// ...
$result = $iterator.next();
}
基本概念基本就是这些,接下来看下使用场景Iterator的使用场景:默认调用场景:for....of...循环, 解构赋值, 扩展运算符, yield*关键字for....of...循环, 解构赋值, 扩展运算符, yield*关键字ES6 借鉴 C++、Java、C# 和 Python 语言,引入了for...of循环,作为遍历所有数据结构的统一的方法for...of这里主要介绍下yield*,其余几个都比较好理解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 }

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()
for...ofArray.from()Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]]))new Map([['a',1],['b',2]])Promise.all()Promise.race()知识拓展:知识拓展遍历器对象的 return(),throw()return方法在循环退出或者报错时调用throw方法主要是配合 Generator 函数使用(详见generator)throw计算生成的数据结构在原有数据结构基础上计算生成的数据结构,例如Object,Map,Set,Array的entries(),keys(), value()方法生成的数据结构,默认具有iterator接口类似数组对象类似数组对象常见:字符串,NodeList节点对象,参数arguments常见:字符串,NodeList节点对象,参数arguments1,并不是所有类似数组的对象都具有 Iterator 接口1,并不是所有类似数组的对象都具有 Iterator 接口2,对于类数组对象可以通过Array.From()将类数组对象转化为数组对象2,对于类数组对象可以通过Array.From()将类数组对象转化为数组对象3,for-of可以识别32 位 UTF-16 字符
for (let x of 'a\uD83D\uDC0A') {
console.log(x);
}

for (let x of 'a\uD83D\uDC0A') {
console.log(x);
}
for-of和其他遍历方法对比:for循环,forEach循环,for...in...循环forEach循环无法中途跳出forEach循环无法中途跳出for...in循环有几个缺点(for...in循环主要是为遍历对象而设计的,不适用于遍历数组),for...in循环有几个缺点(for...in循环主要是为遍历对象而设计的,不适用于遍历数组),for...infor...in

数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。

for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。

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

有着同for...in一样的简洁语法,但是没有for...in那些缺点。

不同于forEach方法,它可以与break、continue和return配合使用。

提供了遍历所有数据结构的统一操作接口。
有着同for...in一样的简洁语法,但是没有for...in那些缺点。for...infor...in不同于forEach方法,它可以与break、continue和return配合使用。forEachbreakcontinuereturn提供了遍历所有数据结构的统一操作接口。参考:http://es6.ruanyifeng.com/http://es6.ruanyifeng.com/感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools./code/HtmlJsRun测试上述代码运行效果。在线HTML/CSS/JavaScript代码运行工具在线HTML/CSS/JavaScript代码运行工具http://tools./code/HtmlJsRun关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》javascript面向对象入门教程JavaScript错误与调试技巧总结JavaScript数据结构与算法技巧总结JavaScript遍历算法与技巧总结JavaScript数学运算用法总结希望本文所述对大家JavaScript程序设计有所帮助。