背景
本文是一篇翻译文章,看到原文《Union, intersection, difference, and more are coming to JavaScript Sets》感觉内容非常不错,而且前端也会用到集合的计算,就决定翻译并整理一下。内容顺序跟原文有所出入,按印象中数学集合的定义进行整理的。
JavaScript Set 添加新功能了,子、交、并、补轻松搞定,一起来看看!
引言
JavaScript Set 是在 ES2015 规范中被引入的集合结构,但是它的功能并不完整:
- 创建
- 增
- 删
- 查
除此之外想要实现集合的其他功能,如计算子集、交集等,就需要自定义函数来实现。幸运的是,基于 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
在浏览器里面控制台输入上面的代码,小测一下的结果:
集合功能适用场景:
- 处理不重复数据值。
- 高效校验集合中是否存在某元素。
- 从 Array 或其他迭代类型转换为集合并去重。
对于更复杂的集合计算功能,我们之前只能自己写函数了。为什么对这个文章感兴趣呢?因为上个月刚好写过两个集合的交集的实现。有了新功能,就不用费劲吧啦的自己写了!
集合的新功能
Set 增加了下列新方法:
- 子,
isSubsetOf/isSupersetOf/isDisjointFrom
- 交,
intersection
- 并,
union
- 补,
difference/symmetricDifference
在谷歌 Chrome 122+ 或 Safari 17+ 浏览器里面可用测试这些新功能。
子集
isSubsetOf
方法用来测试某个集合的元素是否全部包含在另一个集合中;- 反向操作
isSupersetOf
,某集合包含另一个集合的全部元素; 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
测试结果:
交集
Set.prototype.intersection(other)
方法求两个集合的交集:
const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);
const frontAndBackEnd = frontEndLanguages.intersection(backEndLanguages);
测试结果:
并集
用
Set.prototype.union(other)
方法求两个集合的并集:
const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);
const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);
const allLanguages = frontEndLanguages.union(backEndLanguages);
测试结果:
补集
difference
计算集合在全集中的补集,全集减去另一个集合剩下的部分。
测试代码:
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);
测试结果:
symmetricDifference
,全集中除去交集部分:
测试代码:
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);
测试结果,全集相同的话,不同集合调用此方法的结果相同:
支持状况
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
- 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 集合不完整了!