一.Iterator (遍历器)的概念:
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只
要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Iterator的作用有三个:
一是为各种数据结构,提供一个统一的、简便的访问接口;
二是使得数据结构的成员能够按某种次序排列;
三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
1.在ES6中,有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构:
let arr = ['a','b','c'];
let it = 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}
2.对象(Object)之所以没有默认部署Iterator接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需
要开发者手动指定。
本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。
不过,严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作Map结构使用,ES5没有Map结构,
而ES6原生提供了。
(1).一个对象如果要有可被for...of循环调用的Iterator接口,就必须在Symbol.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}; } else { 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 }
(2).代码首先在构造函数的原型链上部署Symbol.iterator方法,调用该方法会返回遍历器对象iterator,调用该对象
的next方法,在返回一个值的同时,自动将内部指针移到下一个实例。
function Obj(value) { this.value = value; this.next = null; }
Obj.prototype[Symbol.iterator] = function() { var iterator = { next: mynext };
var current = this;
function mynext() { if (current) { var value = current.value; current = current.next; return { done: false, value: value }; } else { return { done: true }; } } return iterator; }
var one = new Obj(1); var two = new Obj(2); var three = new Obj(3);
one.next = two; two.next = three;
for (var i of one){
console.log(i); // 1 2 3 }
(3).类似数组的对象调用数组的Symbol.iterator方法的例子:
let iterable = { 0: 'a', 1: 'b', 2: 'c', length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // 'a', 'b', 'c' }
(4).普通对象部署数组的Symbol.iterator方法,并无效果:
let iterable = { a: 'a', b: 'b', c: 'c', length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // undefined, undefined, undefined }
二.for...of循环:
一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for...of循环遍历它的成员。
也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。
for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator对象,以及字符串。
1.for...of循环可以代替数组实例的forEach方法:
const arr = ['red', 'green', 'blue'];
arr.forEach(function (element, index) { console.log(element); // red green blue console.log(index); // 0 1 2 });
for(let i of arr){
console.log(i); // red green blue
}
2.JavaScript原有的for...in循环,只能获得对象的键名,不能直接获取键值。ES6提供for...of循环,允许遍历获得
键值:
var arr = ['a','b','c','d'];
for(let a in arr){
console.log(a); // 0 1 2 3
}
for(let a of arr){
console.log(a); // a b c d
}
3.for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。这一点跟for...in循环也不一样:
let arr = [3,5,7];
arr.hello = 'hello';
for(let i in arr){
console.log(i); // "0","1","2","3"
}
for(let i of arr){
console.log(i); // "3","5","7"
}
转载于:https://www.cnblogs.com/zhihaospace/p/6242838.html