15Iterator和for方法

2017-10-30  本文已影响0人  我_巨可爱

Iterator 概念

遍历器本质上就是一个指针对象

  1. 只有布置了遍历器接口,才可遍历。遍历器接口是[Symbol.iterator]

Iterator 作用

  1. 为各种数据结构提供一个统一的访问接口
  2. 使得数据结构的成员能够按照某种次序排序
  3. for of提供接口

Iterator 遍历过程

默认 Iterator 接口

注意,对象没有Iterator接口

  1. 原生具备 Iterator 接口的数据结构如下
  1. object 不具备原生Iterator接口,需要在[Symbol.iterator]上布置。生成的每项形式为[key,val]
// 为一个类数组对象布置 Iterator 接口
let obj = {
  0:'y',
  1: 'f',
  length: 2,
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
      next() {
        if (index < self.length) {
          return {
            value: [index,self[index++]],
            done: false
          };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};
// 布置到 Object 上
Object.prototype[Symbol.iterator] = function () {
}

通过遍历器实现指针结构的例子

// 指针结构
// 数据结构
function Obj(value) {
    this.value =value;
    this.next = null;
}
// 布置遍历接口
Obj.prototype[Symbol.iterator] = function () {
    var iterator = { next: next };

    var current = this;
    function next() {
        if (current) {
            val 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);
}

生成 Iterator 方式

var arr = [1,2,3];
var iterator = arr[Symbol.iterator]();

默认调用Iterator接口的场合

  1. 解构赋值
  1. 扩展运算符
  1. yield*
  2. 其他场合
// 解构赋值
let set = new Set().add('a').add('b').add('c');
let [x,y] = set;

字符串的 Iterator 接口

// 使用字符串原生的遍历器接口
var str = 'hi';
var iterator = str[Symbol.iterator]();

iterator.next()  // { value: "h", done: false }
iterator.next()  // { value: "i", done: false }
iterator.next()  // { value: undefined, done: true }

遍历器对象的return(),throw()

for of中使用break或者continue提前退出,会调用return方法

//遍历器,必须返回一个包含next方法的对象
// 可选的返回一个包含了throw方法和return方法的对象
function ite() {
    return {
        next() {
            return {done: false}
        },
        return() {
            file.close();
            return { done: true }
        }
    }
}
// throw 方法不常用

for of循环

数组

// for in 获取的是键名,包含了数组的索引和属性,甚至原型上的属性
var arr = [7,9,0];
arr.foo = 'bar';
for (let i in arr) {
    console.log(i);  // '0','1','2','foo'
}
// for of 获取的是数组每项的值
for (let i of arr) {
    console.log(i);  // '7','9','0'
}

Set 和 Map 解构

计算生成的数据结构

数组,Set,Map部署了下面三个方法,这些方法都返回遍历器对象

  1. entries()
  2. keys()
  3. values()

类似数组的对象

并不是所有类似数组的对象都有 Iterator 接口,可以使用Array.from将其转化为数组,再使用for of方法

对象

普通对象,不能直接使用for of,会报错。解决方法:

  1. 使用Object.keys()生成一个由对象属性值组成的数组,再使用for of
  2. 另一个方法使用Generator将对象包装一下
  3. 可以在对象实例上直接布置[Symbol.iterator],也可以在对象原型链上布置[Symbol.iterator]。部署类数组对象的[Symbol.iterator]和普通对象的[Symbol.iterator]方法不同
// 使用 Generator 将对象包装一下
function* entries(obj) {
    // 使用的是Object.keys而不是for in 循环
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

for (let [key, value] of entries(obj)) {
  console.log(key, '->', value);
}
上一篇 下一篇

猜你喜欢

热点阅读