JavaScript迭代器

本文深入讲解JavaScript中的迭代器概念,包括初始迭代器、可迭代协议、迭代器协议等内容,并提供了自定义迭代器的具体实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初始迭代器

说到迭代器,大家是不是马上就能想到ArrayMapSet这些名词呢?

所以这些就是迭代器。。。。。吧?

答案是:错!惊不惊喜?意不意外?

说到迭代器这个概念,首先我们应该明确:迭代器(Iterator)只是一个接口,而ArraySetMap是我们熟知的不同的数据结构,而这些数据结构他们原生的就已经实现了这个Iterator接口。除开这几个数据结构,还有StringArgumentsTypedArray以及DOM中的NodeListCollection

总结:Array、Set、Map、Arguments、String、NodeList、Collection、TypedArray

实现Iterator接口后,相应的数据结构就具备了迭代能力(如下)

let arr = [1,2,3];
for(let ele of arr) {
  console.log(ele);
}
// 1
// 2
// 3

可迭代协议

可以通过检查实例的[Symbol.iterator]属性,来判断是否存在默认迭代器属性(也就是判断是否实现了迭代器接口

  let arr = new Array();
  let str = new String();
  let map = new Map();
  let set = new Set();
  // 当然还有一些NodeList等DOM集合类型

  console.log(arr[Symbol.iterator]);  // ƒ values() { [native code] }
  console.log(str[Symbol.iterator]);  // ƒ [Symbol.iterator]() { [native code] }
  console.log(map[Symbol.iterator]);  // ƒ entries() { [native code] }
  console.log(set[Symbol.iterator]);  // ƒ values() { [native code] }
  
  console.log(arr[Symbol.iterator]());  // 返回迭代器 Array Iterator {}
  console.log(str[Symbol.iterator]());  // 返回迭代器 StringIterator {}
  console.log(map[Symbol.iterator]());  // 返回迭代器 MapIterator {}
  console.log(set[Symbol.iterator]());  // 返回迭代器 SetIterator {}

如果对象原型链上的父类实现了Iterable接口,那这个对象也就实现了这个接口

  class SonArray extends Array {}
  let son_arr = new SonArray(11,23,34);
  /* 包含[Symbol.iterator]属性 */
  console.log(son_arr[Symbol.iterator]().__proto__.__proto__);  // {Symbol(Symbol.iterator): ƒ}

  for(let ele of son_arr) {
    console.log(ele);
  }
  // 11
  // 23
  // 34

迭代器协议

为什么实现了迭代器接口就可以具有遍历的能力呢?

我们通过查看实例的Symbol.iterator方法的返回值,可以发现返回的迭代器对象的原型对象上实现了next()才使得数据结构具有了迭代的能力(后面有通过next()自定义实现迭代器方式)

  let arr = new Array(12,23);
  let iter = arr[Symbol.iterator]();
  console.log(iter);   // Array Iterator {}

  console.log(iter.next());  // {value: 12, done: false}
  console.log(iter.next());  // {value: 23, done: false}
  console.log(iter.next());  // {value: undefined, done: true}
  console.log(iter.next());  // {value: undefined, done: true}

如果可迭代对象在迭代期间被修改,那么迭代器也会反映相应的变化

  let arr = ['fly','swim'];
  let iter = arr[Symbol.iterator]();

  console.log(iter.next());  // {value: "fly", done: false}

  // 添加值
  arr.splice(1, 0, 'code');

  console.log(iter.next());  // {value: "code", done: false}
  console.log(iter.next());  // {value: "swim", done: false}
  console.log(iter.next());  // {value: undefined, done: false}

自定义迭代器

当你真的搞清楚了迭代器的原理,你就可以手动的给任何数据结构添加可迭代能力

下面针对不同版本自定义了不同的实现方式,供大家参考

ES5

  function Number(num1, num2, num3) {
    this.num1 = num1;
    this.num2 = num2;
    this.num3 = num3;
    this.args = arguments;
  }
  
  Number.prototype[Symbol.iterator] = function() {
    // 定义计数器
    let count = 0;
    // 存储参数集合
    let Args = this.args;
    return {
      next() {
        if(count < Args.length) {
          return { done: false, value: Args[count++] };
        }else {
          return { done: true, value: undefined }; 
        }
      }
    }
  };
  
  let numList = new Number(11,23,34);
  console.log(numList);

  for(let ele of numList) {
    console.log(ele);
  }
  // 11
  // 23
  // 34
  
  for(let ele of numList) {
    console.log(ele);
  }
  // 11
  // 23
  // 34

ES6

class Person {
    constructor(name,age,skill) {
      this.name = name;
      this.age = age;
      this.skill = skill;
      this.Args = arguments;
    }

    // 实现Iterator接口
    [Symbol.iterator]() {
      // 定义计数器
      let count = 0;
      // 存储所有参数
      let AllArgs = this.Args;
      /* 
        返回一个迭代器对象
          - 这个对象需要实现next()方法
      */
      return {
        next() {
          if(count < AllArgs.length) {
            return { done: false, value: AllArgs[count++] };
          }else {
            return { done: true, value: undefined };
          }
        }
      };
    }

  }

  let person = new Person('leo',20,'play code');
  console.log(person);

  let iter = person[Symbol.iterator]();
  console.log(iter.next());  // {done: false, value: "leo"} 
  console.log(iter.next());  // {done: false, value: 20}
  console.log(iter.next());  // {done: false, value: "play code"}
  console.log(iter.next());  // {done: true, value: undefined}
  console.log(iter.next());  // {done: true, value: undefined}

  for(let ele of person) {
    console.log(ele);
  }
  // leo
  // 20
  // play code
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值