ES6 Set实例能否使用数组迭代方法?

4

我正在使用ES6 Set实例,需要对它们应用一些转换。如果它们是数组,这些转换将是简单的。下面是一个示例:

let s = new Set;
s.add(1);
s.add(2);
s.add(3);
let n = s.filter(val => val > 1); // TypeError, filter not defined
let n = Array.prototype.filter.call(s, val => val > 1); // []

我希望结果可以是新的Set或数组。我还想使用其他的数组解析方法,比如 filter, map, reduce等。我也希望ES6 Map实例有类似的行为。
这是否可行?还是说我需要使用原生JS数组?

1
根据MDN的说法,没有任何过滤方法,但是您可以使用for (let item of s)来制作自己的过滤方法。 - Robert
1
顺便提一下,filter、map、reduce等并不是“数组推导方法”,它们只是“数组方法”。 - Jaromanda X
@JaromandaX 好观点。已更改。 - Andrew Eisenberg
可能是如何在JavaScript中映射/减少/过滤Set?的重复问题。 - Bergi
2个回答

6

你可以使用数组获取s的值

Array.from(s.values())

Array.from文档指出它从类似数组或可迭代对象创建一个新的Array实例。

Set.values返回一个包含Set对象中每个元素值的新迭代器对象,按插入顺序排列。

因此,您的代码变成了

let s = new Set;
s.add(1);
s.add(2);
s.add(3);
let n = Array.from(s.values()).filter(val => val > 1)

Array.from 正是我正在寻找的。 - Andrew Eisenberg

1
您不能直接在Set或Map对象上使用Array方法。 数组方法期望.length和[n]索引,这不是Set或Map的工作方式。
您可以使用Array.from(s)将Set转换为数组,也可以创建自己的方法直接在Set或Map上操作。 如果您经常这样做并且期望的最终结果是Set或Map,则最好不要转换为Array,修改,然后再转换回来。 此外,将Map转换为数组并不那么简单,因为您既有键又有值(可能必须是对象数组)。
例如,您可以像这样为Set对象创建自己的.filter()方法:

Set.prototype.filter = function(fn) {
    let result = new Set();
    for (let val of this) {
       if (fn(val, this) === true) {
           result.add(val);
       }
    }
    return result;
}

let s = new Set;
s.add(1);
s.add(2);
s.add(3);
let n = s.filter(val => val > 1); 


// log the output

// log output
document.write("Set {" + Array.from(n).join(", ") +"}");

类似的方法也可以用于其他数组方法。

我可能最终会做这样的事情,但我更喜欢一开始就简单化。我将答案授予@Jaromanda X,因为他最先回答了。 - Andrew Eisenberg
@AndrewEisenberg - 但是,如果你想最终得到一个Set,其实没有必要将其转换为数组,然后再转回Set,只是为了避免在一次实用程序方法中多写几行代码 - 在我看来。 - jfriend00
此时不需要得到一个集合,因为它是作为 AngularJS 过滤器的一部分使用的。实际上,在最终结果中,总是需要一个数组,因为在用户界面中顺序很重要。 - Andrew Eisenberg
@AndrewEisenberg - 好的。如果顺序很重要,那么我想知道为什么一开始它是在一个Set中。 - jfriend00
数据实际上存储在一个映射中,由UI不关心的索引键控。这有助于快速进行服务器更新。UI将根据情况(例如-减少、映射、排序、过滤)通过多个过滤器显示数据。 - Andrew Eisenberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接