在ES6中,有iterator.next();有没有办法提供iterator.previous()?

时间:2016-03-10 16:19:47

标签: javascript set ecmascript-6

完整的ES6 Compatibility table。刚刚进入Set()

const set = new Set();
set.add('foo');
set.add('baz');

const iterator = set.values();
iterator.next(); // { value: "foo", done: false }
iterator.next(); // { value: "baz", done: false }

是否可以编写类似于iterator.next()的方法,但它会向后迭代而不是向前迭代(即iterator.previous())?

4 个答案:

答案 0 :(得分:3)

values()返回一个迭代器对象,不可能向后迭代它们,因为JavaScript迭代器对象可能是无限的。例如,考虑一下

function * Counter() {
    "use strict";
    var i = 0;
    while (1) {
        yield i++;
    }
}

现在,您可以使用Counter()创建一个永远不会结束的迭代器。因此,通常情况下,倒退不是迭代器的选项。

如果您非常需要像backIterator这样的东西,那么您必须维护迭代器生成的值,然后根据next调用来回移动。

答案 1 :(得分:0)

我担心没有JS方法可以做到这一点,但是没有人阻止你将变量中的先前值保存并从中读取。

答案 2 :(得分:0)

尽管您目前无法为迭代器提供类似于previous()方法的next()方法,但其他答案均不正确。您可以通过更改迭代器的next()方法来向后遍历ES iteration protocol中的任何迭代。

真正的罪魁祸首是您需要确定是要迭代还是向后。当前,您不能同时执行两项操作,因为必须重写迭代器中的next()方法才能使它向后工作。

继续使用Set对象的示例,您可以覆盖values()方法并提供自己的可迭代迭代器,如下所示:

const set = new Set();
set.add('foo');
set.add('baz');

const iterator = set.values();
console.log(iterator.next()); // { value: "foo", done: false }
console.log(iterator.next()); // { value: "baz", done: false }

set.values = function () {
  const reversedContents = Array.from(this);
  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      const isDone = reversedContents.length === 0;
      return {
        value: reversedContents.pop(),
        done: isDone
      };
    }
  };
}

const reverseIterator = set.values();
console.log(reverseIterator.next()); // { value: "baz", done: false }
console.log(reverseIterator.next()); // { value: "foo", done: false }

这是不理想的,因为它会从集合中创建一个数组以便从集合中获取最后一个元素。

答案 3 :(得分:0)

没有什么可以阻止您这样做的,例如,下面通过包装Set

您显然无法直接在previous()上进行迭代,但是您可以手动调用它,也可以仅通过调用previous()来切换方向,然后进行反向迭代。

values() {
  const items = [...set.values()];
  let index = -1;

  return {
    [Symbol.iterator]() {
      return this;
    },

    next() {
      var item = items[index + 1];
      if (item) {
        return {
          value: item,
          done: false
        };
      }
      return { done: true };
    },

    previous() {
      var item = items[index - 1];
      if (item) {
        return {
          value: item,
          done: false
        };
      }
      return { done: true };
    }
  };
}