Iterator 和 for...of 循环

68 阅读2分钟

Iterator 和 for...of 循环

什么是Iterator
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署
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};
    }
  };
}

模拟的Iterator要具备的条件
    1.拥有next方法用于依次遍历数据结构的成员
    2.每次遍历返回一个对象{done:xxx,value:xxx}
        + done 记录是否遍历完成
        + value 当前遍历的结果
默认 Iterator 接口
一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是“可遍历的”(iterable)。ES6 规定,默认的 Iterator
接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,
就可以认为是“可遍历的”(iterable)。

原生具备 Iterator 接口的数据结构如下。
    Array
    Map
    Set
    String
    TypedArray
    函数的 arguments 对象
    NodeList 对象
for...of遍历原理和重写Iterator 接口
let arr = [1, 2, 3]
for (const item of arr) {
    //当使用for...of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口。 
    Symbol.iterator返回一个对象包含next方法的对象执行next方法返回{done:boolean,value:xxx},done为true时执行结束,
    为false是会吧value的值赋值给item
    console.log(item) // 1 2 3
}
arr[Symbol.iterator] = function () {
    
    let arr = this
    let index = 0
    return {
        next() {
            if (arr.length-1 < index) {
                return {
                    done: true,
                    value: undefined
                }
            }
            return {
                done: false,
                value: arr[index++]
            }
        }
    }
}
for (const item of arr) {
    console.log(item)
    // 1 2 3
}
如何使用for...of 遍历对象
//对象(Object)没有默认部署 Iterator 接口,想使用必须写Iterator方法
let obj = {
    name:'xxx',
    age:24
}
Object.prototype[Symbol.iterator] = function() {
    let arr = Object.keys(this).concat(Object.getOwnPropertySymbols(this))
    let index = 0
    return {
        next() {
            if (arr.length-1 < index) {
                return {
                    done: true,
                    value: undefined
                }
            }
            return {
                done: false,
                value: arr[index++]
            }
        }
    }
}
for (const item of obj) {
    console.log(item)//xxx 24
}