我需要对JavaScript Iterables进行深入解释。

时间:2017-09-14 12:07:35

标签: javascript

为什么我们需要它们以及如何使用它们以及将Iterable功能添加到没有它的对象。这看起来像是一般只是略读的主题。

1 个答案:

答案 0 :(得分:2)

我无法相信这里尚未得到解答,但我找不到。

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

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

如果调用者在用尽之前完成调用,则可以显式关闭保留在文件句柄等资源上的Iterables。例如,我们将使用带有readFromFilegetNextLine函数的假设文件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的this post

如果您的迭代器是生成器函数,就像我上面的无数计数数列表一样,您可以通过yield关键字pass it values

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迭代。