日常生活的交流与学习

首页 新随笔 联系 管理

迭代器

什么是迭代器

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

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

Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

内置的迭代器

image-20220220230255892

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 }

可迭代对象

  1. 普通对象不可迭代,所以不能使用for...of...进行遍历
  2. 可迭代对象,或者说实现了迭代器的对象,可以使用for...of...进行遍历
const iterableObj = {
  names: ['a', 'b', 'c'],
  [Symbol.iterator]: function () {
    let index = 0;
    return {
      next: () => {
        return index < this.names.length
          ? { done: false, value: this.names[index++] }
          : { done: true, value: undefined };
      },
    };
  },
};

const iterator = iterableObj[Symbol.iterator]();
console.log(iterator.next()); //=> { done: false, value: 'a' }
console.log(iterator.next()); //=> { done: false, value: 'b' }
console.log(iterator.next()); //=> { done: false, value: 'c' }
console.log(iterator.next()); //=> { done: true, value: undefined }

// 普通对象是不能使用迭代器的
// const obj = {
//   name: 'Alice',
//   age: 19,
//   sex: 'male',
// };
// for (let item of obj) {
//   console.log(item); //=> TypeError: obj is not iterable
// }

// 可迭代的对象,或者说里面实现了迭代器的对象,是可以使用for...of...进行遍历的
for (let item of iterableObj) {
  console.log(item); //=> a
  //=> b
  //=> c
}

封装一个数组的迭代器

const 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) {
  let nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

自定义类的可迭代性

class Classroom {
  constructor(address, name, students) {
    this.address = address;
    this.name = name;
    this.students = students;
  }

  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        return index < this.students.length
          ? { done: false, value: this.students[index++] }
          : { done: true, value: undefined };
      },
    };
  }
}

const c1 = new Classroom('Beijing', 'Xuexi', ['Alice', 'Bruce', 'Celina']);
const iterator = c1[Symbol.iterator]();
console.log(iterator.next()); //=> { done: false, value: 'Alice' }
console.log(iterator.next()); //=> { done: false, value: 'Bruce' }
console.log(iterator.next()); //=> { done: false, value: 'Celina' }
console.log(iterator.next()); //=> { done: true, value: undefined }

console.log('------------------');
for (let item of c1) {
  console.log(item);
  //=> Alice
  //=> Bruce
  //=> Celina
}

迭代器的提前终止

image-20220221100842892

  1. 迭代器如果执行iteator.return(),那么就会执行return()里面的语句
class Classroom {
  constructor(address, name, students) {
    this.address = address;
    this.name = name;
    this.students = students;
  }

  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        return index < this.students.length
          ? { done: false, value: this.students[index++] }
          : { done: true, value: undefined };
      },
      return: () => {
        console.log('迭代器提前终止了~~~');
      },
    };
  }
}

const c1 = new Classroom('Beijing', 'Xuexi', ['Alice', 'Bruce', 'Celina']);
const iterator = c1[Symbol.iterator]();
console.log(iterator.next()); //=> { done: false, value: 'Alice' }
console.log(iterator.return());

posted on 2022-02-21 10:11  lazycookie  阅读(35)  评论(0编辑  收藏  举报