MarkArch 2019-06-26
本章我们将学习 ES6 中的 Set(集合) 及 WeakSet 集合 的相关用法及使用场景。
Set 集合是 ES6 引入的新的内置对象类型,其特点同数学意义的集合,即集合内所有元素不重复(元素唯一)。
要了解 Set 集合,我们可以先看看数组,ES6 之前数组类似于数学意义上 集合,但是差异在于数组元素值是可重复。
// 数组 let nums = [1, 2, 3, 4, 5] console.log(nums)// [1, 2, 3, 4, 5] nums.push(1) console.log(nums)// [1, 2, 3, 4, 5, 1] // 集合 let sLang = new Set(['javascript', 'java', 'c++', 'php', 'javascript']) console.log(sLang)// Set {"javascript", "java", "c++", "php"}
对比数组 nums 和集合 sLang,数组可以加入重复数据,而集合的所有元素是唯一的不允许重复。
① 申明空集合
// 创建空集合 let s = new Set(); console.log(s)// Set {} s.add('php') console.log(s)//Set {"php"}
② 申明初始值集合
let s = new Set(['php', 'javascript']) console.log(s)// Set {"php", "javascript"}
③ 语法
new Set([iterable]);申明集合时,构造函数里可选接收一个可迭代对象(iterable)。
目前支持可迭代协议的可迭代对象有 Array, [Map], Set, String, TypedArray, arguments对象等.
所以一下初始化都是合法的
// string let str = new Set('name') console.log(str)// Set {"n", "a", "m", "e"} // set let strSet = new Set(str) console.log(strSet)// Set {"n", "a", "m", "e"} // array let nums = new Set([1, 2, 3]) console.log(nums)// Set {1, 2, 3} //arguments function add(...nums) { let args = new Set(arguments) return args } console.log(add(1));// Set {1} console.log(add(1, 2));// Set {1, 2}
常见的操作有添加(add)、删除(delete)、清空(clear)、判断是否存在(has)、获取所有值(values) 及获取集合元素个数
let lang = new Set(['javascript', 'java', 'c++', 'php', 'javascript']) console.log(lang)// Set {"javascript", "java", "c++", "php"} // add lang.add('ruby') console.log(lang)// Set {"javascript", "java", "c++", "php", "ruby"} // delete lang.delete('java') console.log(lang)// Set {"javascript", "c++", "php", "ruby"} // 判断是否存在 python,javascript console.log(`has python: ${lang.has('python')}`)// has python: false console.log(`has javascript: ${lang.has('javascript')}`)// has javascript: true // 获取所有元素 console.log(lang.values()) // SetIterator {"javascript", "c++", "php", "ruby"} console.log(lang.keys()) // SetIterator {"javascript", "c++", "php", "ruby"} // 获取个数 console.log(lang.size);// 4 // 清空 lang.clear() console.log(lang);// Set {}
Set 集合是一个可迭代的对象,所以可以使用 for of 进行迭代获取所有数据。
let lang = new Set(['javascript', 'java', 'c++', 'php', 'javascript']) for (let l of lang) { console.log(l); }
WeakSet 和 普通的 Set 相似,不同点在于:
为什么没有 clear 方法,阮一峰老师的 ES6 教程中有过解释:
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为0,垃圾回收机制就不会释放这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。