我需要对 JavaScript Iterables 进行深入的解释。 [已关闭]

问题描述 投票:0回答:1

为什么我们需要它们以及如何使用它们以及将 Iterable 功能添加到不具有 Iterable 的对象中。这似乎是一个一般来说只是被略过的话题。

javascript ecmascript-6 iterator generator
1个回答
3
投票

JavaScript 迭代器使用众所周知的符号

Symbol.iterator
来定义一个函数,该函数在调用时返回一个对象。该对象有一个方法
next
,它返回另一个具有两个属性的对象:
value
(迭代器的当前值)和
done
(迭代器是否完成)。示例:

const foo = {};
foo[Symbol.iterator] = function* () {
  let i = 0;
  yield ++i;
};

let iter = foo[Symbol.iterator]();
iter.next(); // { value: 1, done: false }
iter.next(); // { value: 2, done: false }

请注意,

*
表示生成器函数

迭代器也可以与像

for..of
这样的自动构造一起使用。然而,我上面定义的那个不能与
for..of
一起使用,因为它永远不会完成:循环遍历它的所有属性最终会导致内存不足。所以让我们使用一个数组:

const bar = [1,2];
for (let baz of bar) console.log(baz); // logs 1, 2, stops

所有内置集合(除了弱集合)都可以在实现此接口时以这种方式进行迭代。

如果调用者在耗尽资源之前使用完保留文件句柄等资源的可迭代对象,则可能会显式关闭它们。例如,我们将使用带有

readFromFile
getNextLine
函数的假设文件 API:

const fileReader = {
  [Symbol.iterator] (path) {
    return {
      fileHandle: readFromFile(path),
      next () {
        return {
          value: this.fileHandle.getNextLine(),
          done: false
        }
      }

      return () {
        this.fileHandle.close();
      }
    }
  }
};

可以调用

return
方法来防止文件句柄泄露。有关更多信息,请参阅 Reg Braithwaite 的这篇文章。另请注意,由于我们显式定义了该方法返回的迭代器,因此不需要将其设为生成器函数。

如果您的迭代器是一个生成器函数,如上面我的无限计数列表中所示,您可以通过 yield 关键字

传递它的值

foo[Symbol.iterator] = function* () {
  let i = 0;
  let reset = yield ++i;
  if (reset) i = 0;
};

iter = foo[Symbol.iterator]();
iter.next().value;    // 1
iter.next().value     // 2
iter.next(true).value // 1 again

假设您有一些对象

myObject
,您希望能够迭代其属性。对于下一个示例,我们将忽略
Object.entries

const myObject = {
  a: 1,
  b: 2
};

Object.defineProperty(myObject, Symbol.iterator, {
  value: function* () {
    for (let key in myObject) {
      if (myObject.hasOwnProperty(key)) {
        yield [key, myObject[key]];
      }
    }
  }
});

iter = myObject[Symbol.iterator]();
iter.next(); // { value: ['a', 1], done: false }
iter.next(); // { value: ['b', 2], done: false }
iter.next(); // { value: undefined, done: true }

注意

在 ES 2015 之前,不能保证对象属性具有顺序。如果您在最新的 Chrome/FF/Safari 中运行上述代码,则一切正常,但如果您将其转换为较旧的浏览器,您可能会首先看到

['b', 2]
输出,也可能不会,或者每次迭代时它都可能会发生变化。

现在您对 JavaScript 可迭代的了解可能比您真正想要的还要多。

© www.soinside.com 2019 - 2024. All rights reserved.