JavaScript 的 Set 严格按插入顺序迭代,这是 ES6+ 规范强制要求的默认行为,不存在 preserves 等配置项;keys()、values()、entries() 和 for...of 均遵循该顺序,重复添加不改变位置,删除后重加则排末尾。

JavaScript 的 Set 本身不保证插入顺序在所有场景下“可见”——但现代标准已明确要求它必须保持插入顺序,preserves 并不是 JS 中的有效关键字或选项,你很可能混淆了其他语言(如 Swift 或 Kotlin)的 API 设计。
为什么找不到 preserves 这个参数
JavaScript 的 Set 构造函数没有 preserves、preserveInsertionOrder 或类似配置项。ECMAScript 2015(ES6)起,Set 就被规范明确定义为“按插入顺序迭代”,这是强制行为,不是可选特性。所谓“保持顺序”是它的默认且唯一行为,不存在开关。
-
Set的keys()、values()、entries()和for...of都严格按插入顺序返回 - 旧版 IE 不支持
Set,但只要运行环境支持 ES6+(Chrome 38+、Firefox 13+、Safari 8+、Node.js 0.12+),顺序就一定可靠 - 如果你看到某文档写了
new Set({ preserves: true }),那基本是伪代码、错译,或混入了其他语言的惯用写法
验证插入顺序是否真被保留
最直接的办法是构造一个带时间差/非字典序的 Set,然后遍历输出:
const s = new Set();
s.add('c');
s.add('a');
s.add('b');
for (const item of s) {
console.log(item); // 输出 'c', 'a', 'b' —— 确实是插入顺序
}
- 注意:
Set去重逻辑基于 SameValueZero 比较,不影响顺序;重复添加同一值不会改变已有位置 - 删除再添加会视为新插入,排在末尾:
s.delete('a'); s.add('a');后,'a'会出现在'b'之后 - 不要用
JSON.stringify(s)检查顺序——Set不可直接序列化,结果是{}[object Set],毫无意义
和 Map、Array 的顺序行为对比
容易误判的点在于:不同集合类型“顺序”的稳定性来源不同,Set 的顺序最“无感”,因为它不暴露索引或键名:
-
Map也按插入顺序迭代(keys()/values()/entries()),且键可以是任意类型,比Set多一层映射语义 -
Array的顺序由索引决定,显式可控,但需手动去重(如[...new Set(arr)])才能模拟Set行为 - 反例:
Object在 ES2015 前不保证属性顺序;虽然后来规范对字符串键和数字键做了排序约定,但它本质不是集合结构,也不用于去重场景
真正需要关注的不是“怎么开启顺序”,而是“别意外破坏它”——比如把 Set 转成对象再转回,或用不稳定的第三方 polyfill。原生 Set 在合规环境中就是最省心的有序唯一集合。










