背景

本文是一篇翻译文章,看到原文《Union, intersection, difference, and more are coming to JavaScript Sets》感觉内容非常不错,而且前端也会用到集合的计算,就决定翻译并整理一下。内容顺序跟原文有所出入,按印象中数学集合的定义进行整理的。

JavaScript Set 添加新功能了,子、交、并、补轻松搞定,一起来看看!

引言

JavaScript Set 是在 ES2015 规范中被引入的集合结构,但是它的功能并不完整:

  1. 创建

除此之外想要实现集合的其他功能,如计算子集、交集等,就需要自定义函数来实现。幸运的是,基于 ECMAScript 规范的 TC39 和浏览器已经支持了集合的交集和并集这些新功能。

JavaScript Set 在ES2015 中的功能

第一,集合类的创建:

 1const languages = new Set(["JavaScript", "TypeScript", "HTML", "JavaScript"])

第二,打印集合的大小:

 1languages.size; 

第三,添加元素:

 1languages.add("JavaScript");
 2languages.add("CSS");
 3languages.size; 

第四,删除元素:

 1languages.delete("TypeScript");
 2languages.size; 

第五,校验元素是否存在:

 1languages.has("JavaScript");// => true
 2languages.has("TypeScript");// => false

第六,遍历集合元素:

 1languages.forEach(element => console.log(element))

第七,清空集合:

 1languages.clear();
 2languages.size;

在浏览器里面控制台输入上面的代码,小测一下的结果:

集合功能适用场景:

  1. 处理不重复数据值。
  2. 高效校验集合中是否存在某元素。
  3. 从 Array 或其他迭代类型转换为集合并去重。

对于更复杂的集合计算功能,我们之前只能自己写函数了。为什么对这个文章感兴趣呢?因为上个月刚好写过两个集合的交集的实现。有了新功能,就不用费劲吧啦的自己写了!

集合的新功能

Set 增加了下列新方法:

  1. 子,isSubsetOf/isSupersetOf/isDisjointFrom
  2. 交,intersection
  3. 并,union
  4. 补,difference/symmetricDifference

在谷歌 Chrome 122+ 或 Safari 17+ 浏览器里面可用测试这些新功能。

子集

  1. isSubsetOf 方法用来测试某个集合的元素是否全部包含在另一个集合中;
  2. 反向操作 isSupersetOf,某集合包含另一个集合的全部元素;
  3. isDisjointFrom,一个集合和另一个集合是否存在公共元素,注意是 Disjoint 不存在公共元素返回真。
 1const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
 2const declarativeLanguages = new Set(["HTML", "CSS"]);
 3console.log(declarativeLanguages.isSubsetOf(frontEndLanguages)); 
 4console.log(frontEndLanguages.isSubsetOf(declarativeLanguages));
 5console.log(declarativeLanguages.isSupersetOf(frontEndLanguages)); 
 6console.log(frontEndLanguages.isSupersetOf(declarativeLanguages));
 7
 8const interpretedLanguages = new Set(["JavaScript", "Ruby", "Python"]);
 9const compiledLanguages = new Set(["Java", "C++", "TypeScript"]);
10console.log(interpretedLanguages.isDisjointFrom(compiledLanguages));
11console.log(frontEndLanguages.isDisjointFrom(interpretedLanguages));

测试结果:

交集

Set.prototype.intersection(other) 方法求两个集合的交集:

 1const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"])
 2const backEndLanguages = new Set(["Python", "Java", "JavaScript"])
 3const frontAndBackEnd = frontEndLanguages.intersection(backEndLanguages)

测试结果:

并集

Set.prototype.union(other) 方法求两个集合的并集:

 1const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"])
 2const backEndLanguages = new Set(["Python", "Java", "JavaScript"])
 3const allLanguages = frontEndLanguages.union(backEndLanguages)

测试结果:

补集

  1. difference 计算集合在全集中的补集,全集减去另一个集合剩下的部分。

测试代码:

 1const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
 2const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);
 3const onlyFrontEnd = frontEndLanguages.difference(backEndLanguages);// => Set {"HTML", "CSS"} 
 4const onlyBackEnd = backEndLanguages.difference(frontEndLanguages);// => Set {"Python", "Java"}
 5console.log(onlyFrontEnd);
 6console.log(onlyBackEnd);

测试结果:

  1. symmetricDifference,全集中除去交集部分:

测试代码:

 1const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
 2const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);
 3const onlyFrontEnd = frontEndLanguages.symmetricDifference(backEndLanguages);
 4// => Set {"HTML", "CSS", "Python", "Java"} 
 5const onlyBackEnd = backEndLanguages.symmetricDifference(frontEndLanguages);
 6// => Set {"Python", "Java", "HTML", "CSS"}
 7console.log(onlyFrontEnd);
 8console.log(onlyBackEnd);

测试结果,全集相同的话,不同集合调用此方法的结果相同:

支持状况

As of writing this, the proposal stands at stage 3 in TC39’s process and Safari 17 (released in September 2023) and Chrome 122 (February

  1. have shipped implementations of these methods. Edge follows Chrome closely and Firefox Nightly has support behind a flag, I would expect both of these browsers to ship support soon too.

我测试的时候本机谷歌浏览器版本是128,是直接可用的。上个月写一个筛选公共字段的前端功能,还是自己费劲实现的。如果所有浏览器都支持的话,一行调用就可以搞定了,还是挺轻松的!

待到那时,前端程序员再也不会感到 Set 集合不完整了!

个人笔记记录 2021 ~ 2025