flowers
用JavaScript遍历器iterator实现指针结构;为对象实现iterator接口

2021.08.165 min read

原创声明:未经允许,禁止转载

虽然StringArrayMapSet和一些DOM collection 类型都自带iterator实现,很多时候我们还需要一些自定义的iterator来实现一些自定义的功能和处理。

JavaScript遍历器(iterator)接口可以为不同的数据结构实现统一的访问机制, 因此通过iterator我们可以为自定义的数据结构(比如包含Map成员的数组)部署统一的接口来实现遍历操作。并且通过定义iterator的方式遍历结构我们可以保证遍历/数据处理的顺序。
(iterator接口的实现主要通过for...of结构来使用)

比如:

实现指针结构:
function Node(value) {
  this.value = value;
  this.next = null;
}

Node.prototype[Symbol.iterator] = function () {
  let current = this;
  return {
    next() {
      if (current) {
        let value = current.value;
        current = current.next; // 将指针指向下一个instance
        return { done: false, value: value }; //返回当前instance的值
      } else {
        return { done: true };
      }
    },
  };
};

let one = new Node(1);
let two = new Node(2);
let three = new Node(3);
one.next = two;
two.next = three;

for (const iterator of one) {
  console.log(iterator);
}
// 1
// 2
// 3
为对象实现iterator接口
let obj = {
  data: [1, 2, 3, 4, 5],
};

obj[Symbol.iterator] = function () {
  let index = 0;
  const data = this.data;
  return {
    next() {
      return data[index]
        ? { value: data[index++], done: false }
        : { done: true };
    },
  };
};

let test = obj[Symbol.iterator]();
console.log(test.next()); // { value: 1, done: false }

for (const iterator of obj) {
  console.log(iterator);
}
// 1
// 2
// 3
// 4
// 5
为类似数组的对象简单添加iterator接口结构
let obj = {
  0: "a",
  1: "b",
  2: "c",
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator],
};
for (const iterator of obj) {
  console.log(iterator);
}
// a
// b
// c

但是对于像下面一样属性值不是数组的index结构的普通对象,则不能够简单部署引用数组的Symbol.iterator

let obj = {
  a: "a",
  b: "b",
  c: "c",
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator],
};
for (const iterator of obj) {
  console.log(iterator);
}
// undefined
// undefined
// undefined