【问题标题】:In ES6, there is iterator.next(); is there any way to supply iterator.previous()?在 ES6 中,有 iterator.next();有没有办法提供 iterator.previous()?
【发布时间】:2016-06-25 14:43:02
【问题描述】:

浏览完整的 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())?

【问题讨论】:

标签: javascript set ecmascript-6


【解决方案1】:

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

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

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


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

【讨论】:

  • 从逻辑上讲,你不能在无限的元素集合结束时开始迭代。然而,说这使得迭代器不可能向后迭代是错误的。有关演示,请参阅我的答案。
  • @kleinfreund 我敢肯定你没有读完最后一段。
  • @kleinfreund 好的,谢谢。
【解决方案2】:

虽然此时你无法为迭代器提供类似于next() 方法的previous() 方法,但其他答案并不正确。您可以通过更改迭代器的 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】:

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

    你显然不能直接迭代previous(),但你可以手动调用它,或者只是通过调用previous()来切换方向,然后next现在反向迭代。

    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 };
        }
      };
    }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 变量中需要存储多少先前的值?还是分开重复的数组/迭代器?
      猜你喜欢
      • 2020-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 2020-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多