ES6以后数据结构除了数组和对象,又添加了Map和Set。遍历器是一种接口规格,任何数据结构只要部署这个接口,就能够完成遍历操做javascript
提供了一个指针,经过指针的指向进行遍历操做java
它提供了一个指针,默认指向当前数据结构的起始位置。也就是说,遍历器返回一个内部指针,
第一次调用next方法,将指针指向第一个成员,第二次调用next方法,指针指向第二个成员数组
下面是一个模拟遍历器指针的例子数据结构
function makeIterator(array) { let nextIndex = 0 return { next: function() { return (nextIndex < array.length) ? {value: array[nextIndex++], done: false} : {value: undefined, done: true} } } } let it = makeIterator(['a', 'b']) it.next() // {value: 'a', done: false} it.next() // {value: 'b', done: false} it.next() // {value: 'undefined', done: false}
遍历器是一个对象,具备next方法,调用next方法,就能够遍历事先给定的数据结构this
Iterator接口的目的,就是为全部的数据结构提供一种统一的访问机制,就是for of循环prototype
默认的Iterator接口部署在数据结构的Symbol.iterator
属性,或者说数据结构具备该属性就能够认为是可遍历的指针
有三类数据结构原生具有了Iterator接口:数组、类数组对象、Set和Map,能够直接使用for of方法
而对象须要在Symbol.iterator
的属性上部署遍历器方法,才能够for ofcode
下面是经过遍历器实现指针结构的例子对象
// 在原型链上部署System.iterator方法,调用该方法,会返回遍历器对象iteator。调用该对象的next方法,在返回一个值的同时,自动将内部指针指向下一个实例 function test (value) { this.value = value this.next = null } test.prototype[Symbol.iterator] = function () { let iterator = { next: next // iterator.next是一个function } let current = this function next () { if (current) { let value = current.value let done = current == null current = current.next return { value: value, done: done } } else { return { done: true } } } return iterator } let one = new test(1), two = new test(2), three = new test(3); one.next = two two.next = three for (let i of one) { console.log(i) // 1 2 3 }
还有一种简单操做,对于类数组对象接口
NodeList.prototypoe[Symbol.iterator] = Array.prototype[Symbol.iterator]
默认调用iterator接口的场合
部署Symbol.iterator最简单实现是结合Generator
let myIterable = [] myiIterable[Symbol.iterator] = function* () { yield 1 yield 2 yield 3 } [...myIterable] // [1, 2, 3] // 或者 let obj = { * [Symbol.iterator]() { yield 'hello' yield 'world' } } for (let x of obj) { console.log(x) // hello world }
// 如下状况报错 let e = { a: 1, b: 'bbb' } for (let [key, value] of e) { console.log() // error,e is not iterable } // 使用yield包装一下 function* (obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]] } } for (let [key, value] of entries(obj)) { console.log(key, '->', value) } // a -> 1 // b -> 2 // c -> 3
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 }