JavaScript中的迭代器(iterator)

84 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

提到迭代,我的理解就是将数组或对象中的每个元素一个一个的取出来。很多语言中都有迭代器,学习JavaScript的时候也听过迭代器,但是没有系统的学习过,感觉不简单。但是今天学习了,也很好的理解了。

一、什么是迭代器

在MDN 中这样解释
在 JavaScript 中,迭代器是一个对象,它定义一个序列,并在终止时可能返回一个返回值。 更具体地说,迭代器是通过使用 next() 方法实现 Iterator protocol的任何一个对象,该方法返回具有两个属性的对象: value,这是序列中的 next 值;和 done ,如果已经迭代到序列中的最后一个值,则它为 true 。如果 value 和 done 一起存在,则它是迭代器的返回值。

总的来说:迭代器就是一个对象,是一个可以帮助我们对数据容器进行遍历的对象。
在JavaScript中,每个符合迭代器协议的对象都是迭代器,那迭代器协议是什么?
迭代器协议:是一个特定的next函数,该函数是一个0或1参数的函数,返回一个有两个属性(done、value)的对象。

  • done:Boolean,如果迭代器将序列遍历完,值为true,否则为false。
  • value:迭代器赶回的任何js值,done为true时可省略

二、创建一个数组迭代器

下面是实现的一个数组迭代器

const names = [2, 3, 21];

// 迭代器遍历数组
let index = 0;
const nameIterator = {
  next() {
    if (names.length) {
      return { done: false, value: names[index++] };
    } else {
      return { done: true, value: undefined };
    }
  },
};

console.log(nameIterator.next());  //{ done: false, value: 2 }
console.log(nameIterator.next());  //{ done: false, value: 3 }
console.log(nameIterator.next());  //{ done: false, value: 21 }
console.log(nameIterator.next());  //{ done: , value: undefined }
无限的迭代器

上面的迭代器是一个有限的迭代器,下面实现一个无限的迭代器

//创建一个无限的迭代器
function createNumberIterator(){
    let index = 0
    return {
        next(){
            return {done:false,value:index++}
        }
    }
}

三、可迭代对象

当一个对象实现了迭代器协议,就是一个可迭代对象
这个对象必须要实现@@iterator方法,在代码中使用Symbol.iterator访问该属性

创建一个可迭代对象
const iterableObj = {
  names: [3, 2],
  [Symbol.iterator]: function () {
    let index = 0;
    return {
      next: () => {
        if (index < this.names.length) {
          return { done: false, value: this.names[index++] };
        } else {
          return { done: true, value: undefined };
        }
      },
    };
  },
};

const iterator1 = iterableObj[Symbol.iterator]();
console.log(iterator1.next());   //{ done: false, value: 3 }
console.log(iterator1.next());   //{ done: false, value: 2 }
console.log(iterator1.next());   //{ done: false, value: undefined }

四、迭代器的使用场景

  • 一些方法:for...of...、解构赋值、展开运算符、yield
  • 创建一些对象:new Map(iterator)、new Set(iterator)等
  • 使用一些方法:Promise.all(iterator)等
const arr = [22222, 2, 3, 3];
const str = "wwww111";
const obj2 = { name: "hhe", age: 22 };

for (let i of str) {
  console.log(i, "-------");
}

// 展开运算符
const newArr = [...arr, ...str];
const newObj2 = { ...obj2 }; //用的不是迭代器
console.log(newArr, newObj2);

// 解构赋值
const { name, age } = obj2; //用的不是迭代器
console.log(name, "---------");
const [x, y, z, n] = arr;
console.log(x, y);

五、原生的迭代器对象

String、Array、Map、Set、arguments等

const arr = [22222, 2, 3, 3];
console.log(arr[Symbol.iterator]().next()); //22222

六、监听迭代器中断

const iteratorObj = {
    stus:['lmn','wyy','ll'],
     [Symbol.iterator]() {
        let index = 0;
        return {
          next: () => {
            if (index < this.stus.length) {
              return { done: false, value: this.stus[index++] };
            } else {
              return { done: true, value: undefined };
            }
          },
           //监听迭代器停止 
          return: () => {
            console.log("迭代器停止");
            return {
              done: true,
            };
          },
        };
      }
  }
  
  for (let item of iteratorObj) {
      console.log(item);
      if (item == "wyy") break;
    }

写在最后 学习了迭代器真是是理解了很多东西。迭代器一般会和生成器一起出现的,那么下一篇文章来讲解生成器