1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 18:32:22 +00:00
es6tutorial/docs/iterator.md
2014-04-25 12:24:17 +08:00

3.7 KiB
Raw Blame History

Iterator和for...of循环

Iterator遍历器

遍历器Iterator是一种协议任何对象只要部署这个协议就可以完成遍历操作。在ES6中遍历操作特指for...of循环。

ES6的遍历器协议规定部署了next方法的对象就具备了遍历器功能。next方法必须返回一个包含value和done两个属性的对象。其中value属性是当前遍历位置的值done属性是一个布尔值表示遍历是否结束。


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'
it.next().value // 'b'
it.next().done  // true

上面代码定义了一个makeIterator函数它的作用是返回一个遍历器对象用来遍历参数数组。请特别注意next返回值的构造。

下面是一个无限运行的遍历器例子。


function idMaker(){
    var index = 0;
    
    return {
       next: function(){
           return {value: index++, done: false};
       }
    }
}

var it = idMaker();

it.next().value // '0'
it.next().value // '1'
it.next().value // '2'
// ...

一个对象只要具备了next方法就可以用for...of循环遍历它的值。


for (var n of it) {
  if (n > 5)
    break;
  console.log(n);
}

for...of循环

ES6中任何具备了iterator接口的对象都可以用for...of循环遍历。数组原生具备iterator接口。


const arr = ['red', 'green', 'blue'];

for(let v of arr) {
	console.log(v);
}
\\ red
\\ green
\\ blue

JavaScript原有的for...in循环只能获得对象的键名不能直接获取键值。ES6提供for...of循环允许遍历获得键值。


var arr = ["a", "b", "c", "d"];
for (a in arr) {
  console.log(a);
}
// 0
// 1
// 2
// 3

for (a of arr) {
  console.log(a); 
}
// a
// b
// c
// d

上面代码表明for...in循环读取键名for...of循环读取键值。

对于Set和Map结构的数据可以直接使用for...of循环。


var engines = Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
    console.log(e);
}
// Gecko
// Trident
// Webkit

var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
  console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262

上面代码演示了如何遍历Set结构和Map结构后者是同时遍历键名和键值。

对于普通的对象for...of结构不能直接使用会报错必须部署了iterator接口后才能使用。但是这样情况下for...in循环依然可以用来遍历键名。


var es6 = {
  edition: 6,
  committee: "TC39",
  standard: "ECMA-262"
};

for (e in es6) {
  console.log(e);
}
// edition
// committee
// standard

for (e of es6) {
  console.log(e);
}
// TypeError: es6 is not iterable

上面代码表示for...in循环可以遍历键名for...of循环会报错。

总结一下for...of循环可以使用的范围包括数组、类似数组的对象比如arguments对象、DOM NodeList对象、Set和Map结构、后文的Generator对象以及字符串。下面是for...of循环用于字符串和DOM NodeList对象的例子。


// 字符串的例子

let str = "hello";

for (let s of str) {
  console.log(s);
}
// h
// e
// l
// l
// o

// DOM NodeList对象的例子

let paras = document.querySelectorAll("p");

for (let p of paras) {
  p.classList.add("test");
}