在 ES6 中,有 iterator.next();有什么办法可以提供 iterator.previous() 吗?
In ES6, there is iterator.next(); is there any way to supply iterator.previous()?
完成完整的 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()
)?
恐怕没有 JS 方法可以做到这一点,但是没有人会阻止您将以前的值保存在变量中并从中读取。
values()
returns 一个迭代器对象,不可能向后迭代它们,因为 JavaScript 迭代器对象可能是无限的。例如,考虑这个
function * Counter() {
"use strict";
var i = 0;
while (1) {
yield i++;
}
}
现在,您可以使用 Counter()
创建一个永不结束的迭代器。因此,通常情况下,迭代器不支持倒退。
如果您非常需要像 backIterator 这样的东西,那么您必须维护迭代器产生的值,然后根据 next
调用来回移动。
虽然此时你不能向迭代器提供一个类似于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 }
这并不理想,因为这会从集合中创建一个数组,以便从集合中获取最后一个元素。
没有什么可以阻止你这样做,例如下面通过包装 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 };
}
};
}
完成完整的 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()
)?
恐怕没有 JS 方法可以做到这一点,但是没有人会阻止您将以前的值保存在变量中并从中读取。
values()
returns 一个迭代器对象,不可能向后迭代它们,因为 JavaScript 迭代器对象可能是无限的。例如,考虑这个
function * Counter() {
"use strict";
var i = 0;
while (1) {
yield i++;
}
}
现在,您可以使用 Counter()
创建一个永不结束的迭代器。因此,通常情况下,迭代器不支持倒退。
如果您非常需要像 backIterator 这样的东西,那么您必须维护迭代器产生的值,然后根据 next
调用来回移动。
虽然此时你不能向迭代器提供一个类似于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 }
这并不理想,因为这会从集合中创建一个数组,以便从集合中获取最后一个元素。
没有什么可以阻止你这样做,例如下面通过包装 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 };
}
};
}