ES6 Iterator遍历器

JavaScript 原有的表示“ 集合” 的数据结构, 主要是数组( Array) 和对象( Object), ES6 又添加了 Map 和 Set。 这样就有了四种数据集合, 用户还可以组合使用它们, 定义自己的数据结构, 比如数组的成员是 Map, Map 的成员是对象。 这样就需要一种统一的接口机制, 来处理所有不同的数据结构。

遍历器( Iterator) 就是这样一种机制。 它是一种接口, 为各种不同的数据结构提供统一的访问机制。 任何数据结构只要部署 Iterator 接口, 就可以完成遍历操作( 即依次处理该数据结构的所有成员)。

Iterator 的作用有三个:

  1. 为各种数据结构, 提供一个统一的、 简便的访问接口
  2. 使得数据结构的成员能够按某种次序排列
  3. ES6 创造了一种新的遍历命令for…of循环, Iterator 接口主要给for…of提供服务

Iterator 的遍历过程:

  1. 创建一个指针对象, 指向当前数据结构的起始位置。 也就是说, 遍历器对象本质上, 就是一个指针对象
  2. 第一次调用指针对象的next方法, 将指针指向数据结构的第一个成员
  3. 第二次调用指针对象的next方法, 指针就指向数据结构的第二个成员
  4. 不断调用指针对象的next方法, 直到它指向数据结构的结束位置

每一次调用next方法, 都会返回数据结构的当前成员的信息。 具体来说, 就是返回一个包含value和done两个属性的对象。 其中, value属性是当前成员的值, done属性是一个布尔值, 表示遍历是否结束。

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

在ES6中,有些数据结构原生具备Iterator接口(比如数组),即不用任何处理,就可以被for…of循环遍历,有些就不行(比如对象)。原因在于,这些数据结构原生部署了Symbol.iterator属性,另外一些数据结构没有。凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。

在 ES6 中, 有三类数据结构原生具备 Iterator 接口: 数组、 某些类似数组的对象、 Set 和 Map 结构。

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 } 

上面代码中, 变量arr是一个数组, 原生就具有遍历器接口, 部署在arr的Symbol.iterator属性上面。 所以, 调用这个属性, 就得到遍历器对象。

下面是类似数组的对象调用数组的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'
}

上面提到, 原生就部署 Iterator 接口的数据结构有三类, 对于这三类数据结构, 不用自己写遍历器生成函数,for…of循环会自动遍历它们。 除此之外, 其他数据结构( 主要是对象) 的 Iterator 接口, 都需要自己在Symbol.iterator属性上面部署, 这样才会被for…of循环遍历。

let obj = {
  data: [ 'hello', 'world' ],
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++],
            done: false
          };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};
for(let item of obj){
    console.log(item); //'hello','world'
}

调用 Iterator 接口的场合

(1)解构赋值对数组和 Set 结构进行解构赋值时, 会默认调用Symbol.iterator方法

let set = new Set().add('a').add('b').add('c');  
let [x, y] = set;  
// x='a'; y='b'  
let [first, ...rest] = set;  
// first='a'; rest=['b','c'];  

(2)扩展运算符

//  例一  
var str = 'hello';  
[...str] // ['h','e','l','l','o']  
//  例二  
let arr = ['b', 'c'];  
['a', ...arr, 'd']  
// ['a', 'b', 'c', 'd']  

(3)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 }  

(4)字符串的 Iterator 接口,字符串是一个类似数组的对象, 也原生具有 Iterator 接口

var someString = "hi";  
typeof someString[Symbol.iterator]  
    // "function"  
var iterator = someString[Symbol.iterator]();  
iterator.next() // { value: "h", done: false }  
iterator.next() // { value: "i", done: false }  
iterator.next() // { value: undefined, done: true }  

引自:
http://www.cnblogs.com/zczhangcui/p/6502836.html
http://blog.csdn.net/qq_30100043/article/details/53463471

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值