迭代器和可迭代协议

142 阅读2分钟

迭代器

背景知识

什么是迭代?

  • 从一个数据集合中,按照一定的顺序不断取出数据的过程

迭代和遍历的区别?

  • 迭代强调的是依次取数据,并不保证取多少
  • 遍历强调的是依次取出全部数据

迭代器

  • 对迭代过程的封装,不同的语言中有不同的表现形式,通常为一个对象

迭代模式

  • 一种设计模式,用于统一迭代过程,并规范了迭代器的规格:
    • 迭代器应当具有获取下一个数据的能力
    • 迭代器应当具有判断是否还有下一个数据的能力

JS中的迭代器

JS规定如果一个对象具有next方法,并且该方法返回一个对象,格式如下:

{
    value: 'xxx', // 值
    done: Boolean, // 是否迭代完成
}

则认为该对象是一个迭代器

含义:

  • next方法:用于得到下一个数据
  • 返回的对象
    • value:下一个数据的值
    • done:boolean,是否迭代完成

迭代器创建函数

一个返回迭代器的函数

const arr = [1, 2, 3, 4, 5];

// 迭代器创建函数
function createIterator(arr) {
  let i = 0;
  return {
    next() {
      const result = {
        value: arr[i], // 值
        done: i >= arr.length, // 是否迭代完成
      };

      i++;

      return result;
    },
  };
}

const iterator = createIterator(arr);

let result = iterator.next();
while (!result.done) {
  console.log(result.value);
  result = iterator.next();
}

应用

依次得到斐波那契数列前n位的值

// 依次得到斐波那契数列前n为的值
// 1, 1, 2, 3, 5, 8......

function createFeiBoIterator() {
  let i = 0,
    prev1 = 1, // 前边第一位
    prev2 = 1; // 前边第二位
  return {
    next() {
      if (i < 2) {
        value = 1;
      } else {
        value = prev1 + prev2; // 前边第一位 + 前边第二位
        prev2 = prev1; // 前边第二位 = 前边第一位
        prev1 = value; // 前边第一位 = 当前值
      }
      i++;
      return {
        value,
        done: false,
      };
    },
  };
}

const feiBoIterator = createFeiBoIterator();

// 打印前10位的值
let i = 1;
while (i <= 10) {
  console.log(feiBoIterator.next().value);
  i++;
}

可迭代协议与for-of循环

可迭代协议

ES6规定,如果一个对象具有知名符号属性Symbol.iterator,并且属性值是一个迭代器创建函数,则该对象是可迭代的(iterable)

只要该对象上存在属性**Symbol.iterator**并且值为迭代器创建函数即可(可手动将普通对象变为可迭代对象)

for-of循环

for-of循环用于遍历可迭代对象,格式如下:

//迭代完成后循环结束
for(const item in iterable){
    // iterable:可迭代对象
    // item:每次迭代得到的数据
}

展开运算符与可迭代对象

展开运算符可以将可迭代对象转换为数组。