什么是集合?
回顾之前的数据结构:栈,队列,链表——它们都可以用JS数组来实现,而集合的实现更依赖于Object,相较于对象key:value的结构,集合的key与value其实是同一个,即
{1:1,2:2,'a':'a'}
这种。参考ES6的Set数据结构
- 特性:
- 无重复性:每个元素是互斥的
- 无序性:一个集合中,每个值钱经的地位都相同,元素之间是无序的。
- JS中集合的表示:对象
集合操作方法
- 是否存在:has(value)
- 删除:remove(value)
- 添加:add(value)
- 索引:indexOf()
- 清空:clear()
- 长度大小:size
function SetClass(){
var items= {}
this.has = function(val){
return items.hasOwnProperty(val)
}
this.add = function(val){
if(!this.has(val)){
items[val]=val; // 以值 为key
return val
}
return false
}
this.remove = function (value){
if(!this.has(value)){
delete items[value]
return true;
}
return false;
}
this.clear=function(){
items = {}
}
this.size = function(){
return Object.keys(items).length;
}
this.values = function(){
var values = []
for(let key in items){
if(items.hasOwnProperty(items[i])){
values.push(items[i])
}
}
return values
}
this.print = function(){
console.log(items)
}
}
集合间的操作
- 并集:union
- 交集:intersection
- 差集:difference
并集
this.union = function (otherSet){
var resSet = new SetClass()
var arr = this.values()
for(let i=0;i<arr.length;i++){
resSet.add(arr[i])
}
arr = otherSet.values()
for(let i=0;i<arr.length;i++){
resSet.add(arr[i])
}
return resSet
}
交集
this.intersection = function(otherSet){
var resSet = new SetClass()
var arr = this.values()
for(let i=0;i<arr.length;i++){
if(!otherSet.has(arr[i])){
resSet.add(arr[i])
}
}
return resSet
}
差集
this.differenct = function(otherSet){
var resSet = new SetClass()
let values = this.values()
for(let i=0;i<values.length;i++){
if(!otherSet.has(values[i])){
resSet.add(values[i])
}
}
return resSet
}
ES6 内置新数据结构
- Set : 集合
- WeakSet: 弱集合, 只能添加一个object类型的值作为元素
相关API操作
var set = new Set(([1,2,3]))
set.forEach((key,value,set)=>{
console.log('key---',key)
console.log('value---',value)
console.log(set)
})
var weakSet = new WeakSet()
weakSet.add('1') //报错
weakSet.add({name:'a'})
ES6实现交集、并集,差集
var set1 = new Set(([1,2,3]))
var set2 =new Set([2,3,4])
// 交集
var intersect = new Set([...set1].filter(item=>set2.has(item)))
// 差集
var different = new Set([...set2].filter(item=>!set1.has(item)))
// 并集
var union = new Set([...set1,...set2])
Set 和 WeakSet的区别
- Set的强引用和WeakSet的弱引用
如上图,声明一个变量obj指向了对象
{name:''ceshi}
,将obj添加到set结构中后,改变obj的指向到null,此时,原Set结构因为是强引用指向原对象,所以该对象不会被 GC回收,仍然保留在内存中,直到使用set.delete删除掉该对象后才能解除引用。而weakSet则是在obj指向改变后,原object会忽略weakset的弱引用而直接被GC回收
- 应用场景:开发中,使用weakSet更灵活,对内存的管理更自动化一些。
一道 ES6面试题
介绍下Set、Map、WeakSet和WeakMap的区别?
- Set:
- 成员不能重复
- 只有键值,没有键名
- 可以遍历,方法有add,delete,has
- WeakSet:
- 成员都是对象
- 成员都是弱引用,随时可以消失,可以用来保存DOM节点,不容易造成内存泄漏
- Map:
- 本质上是键值对的集合,类似集合。其键名可以是非字符串.Object的键值对中的“键”实际是字符串,而Map的键可以是其他类型的值。
- 可以遍历、
- WeakMap:
- 只接受对象作为键名(null除外),不接受其他类型的值作为键名
- 键名所指向的对象,不计入垃圾回收机制
- 不能遍历,方法有get、set、has、delete