JavaScript中Array.from(set)与Array.from(set.values())有何差异?
两种Set转数组写法的差异说明
首先直接给结论:原生JavaScript环境中,两种写法最终生成的数组完全一致,仅存在极其细微的底层逻辑差异,几乎不会影响日常开发。
核心逻辑对齐的原因
ECMAScript标准明确规定:Set的默认迭代器就是Set.prototype.values()方法返回的迭代器,你可以通过下面的代码验证这个规则:
console.log(Set.prototype[Symbol.iterator] === Set.prototype.values) // 输出 true
而Array.from和展开语法...处理可迭代对象时,都是调用对象的Symbol.iterator对应的迭代器来遍历取值,因此不管传入的是Set实例本身,还是set.values()返回的迭代器实例,遍历拿到的值、顺序完全一致,最终生成的数组没有任何区别。
仅有的细微差异
只有以下两个几乎可以忽略的底层区别:
- 后者会多执行一次
values()方法调用,虽然这个调用的性能开销极低,在绝大多数场景下都感知不到,但确实多了一步操作 - 入参类型不同:前者入参是完整的
Set实例,后者入参是SetIterator迭代器对象。如果是自定义继承Set的类,且重写了默认的Symbol.iterator方法,二者的返回结果可能出现差异,示例如下:
const customSet = new Set([1,2,3]) // 自定义默认迭代器,返回值翻倍 customSet[Symbol.iterator] = function* () { for (const val of this.values()) yield val * 2 } console.log([...customSet]) // [2,4,6] console.log([...customSet.values()]) // [1,2,3]
这种自定义修改的场景非常罕见,原生环境不会出现该问题。
适用场景选择
- 日常开发优先选
Array.from(set)或[...set],写法更简洁,可读性更高,没有多余的调用开销 - 以下特殊场景可以选择带
values()的写法:- 代码中同时存在
Map、Set等多种集合类型的转数组操作,统一加.values()可以保持代码风格一致,降低理解成本(例如Map转值数组的写法就是Array.from(map.values())) - 需要显式向其他开发者表明你是取
Set的值来生成数组,排除取键、键值对等其他操作的可能
- 代码中同时存在
内容的提问来源于stack exchange,提问作者Snap
相关产品推荐
相关产品推荐

