JavaScript Set有新功能啦,子、交、并、补轻松搞定

1,238 阅读3分钟

背景

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

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

引言

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

  1. 创建

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

JavaScript Set 在ES2015 中的功能

第一,集合类的创建:

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

第二,打印集合的大小:

languages.size; // => 3

第三,添加元素:

languages.add("JavaScript");
languages.add("CSS");
languages.size; // => 4

第四,删除元素:

languages.delete("TypeScript");
languages.size; // => 3

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

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

第六,遍历集合元素:

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

第七,清空集合:

languages.clear();
languages.size;// => 0

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

image.png

集合功能适用场景:

  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 不存在公共元素返回真。
const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
const declarativeLanguages = new Set(["HTML", "CSS"]);
console.log(declarativeLanguages.isSubsetOf(frontEndLanguages)); // => true
console.log(frontEndLanguages.isSubsetOf(declarativeLanguages));// => false
console.log(declarativeLanguages.isSupersetOf(frontEndLanguages)); // => false
console.log(frontEndLanguages.isSupersetOf(declarativeLanguages));// =>true

const interpretedLanguages = new Set(["JavaScript", "Ruby", "Python"]);
const compiledLanguages = new Set(["Java", "C++", "TypeScript"]);
console.log(interpretedLanguages.isDisjointFrom(compiledLanguages));// => true
console.log(frontEndLanguages.isDisjointFrom(interpretedLanguages));// => false

测试结果:

image.png

交集

image.png

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

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

测试结果:

image.png

并集

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

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

测试结果:

image.png

补集

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

image.png

测试代码:

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

测试结果:

image.png

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

image.png

测试代码:

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);
const onlyFrontEnd = frontEndLanguages.symmetricDifference(backEndLanguages);
// => Set {"HTML", "CSS", "Python", "Java"} 
const onlyBackEnd = backEndLanguages.symmetricDifference(frontEndLanguages);
// => Set {"Python", "Java", "HTML", "CSS"}
console.log(onlyFrontEnd);
console.log(onlyBackEnd);

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

image.png

支持状况

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 集合不完整了!