Skip to content

Es6 中新增了两种数据集合 SetMap

7-1.Set

Set是内部元素不重复存在的可迭代数据集合。

7-1-1.Set的创建

js
var set = new Set()
// Set实例上有size属性 对应的是数组的length属性 表示该集合的数据长度 初始为0
console.log(set.size)
// 1.添加元素
set.add('hello')
set.add('world')
// 重复添加的话 不会起作用
set.add('hello')
// 2.移除元素
set.delete('world')
// 3.是否包含某一元素
console.log(set.has('hello'))
console.log(set.has('world'))
// 4.清空集合
set.clear()

7-1-2.Set与数组

js
// 1.数组转化为Set
var list = ['i', 'love', 'i', 'do']
var set = new Set(list)
// 由于Set实例内的数据是不可重复 所以Set实例会自动对数组进行去重
console.log(set.size)
console.log(set) // Set(3) {'i', 'love', 'do'}

// 2.Set转化为数组
// 由于Set实例实际是可迭代的 所以我们要借助`展开运算符...`
var newList = [...set]
console.log(newList) // ['i', 'love', 'do']

7-1-3.Set的遍历

对应于数组的 forEach 方法,Set 的遍历也有对应的一个 forEach 方法。

js
var set = new Set(['i', 'love', 'my', 'job'])
set.forEach(function(value, key, currentSet) {
  /*
    i i Set(4) {'i', 'love', 'my', 'job'}
    love love Set(4) {'i', 'love', 'my', 'job'}
    my my Set(4) {'i', 'love', 'my', 'job'}
    job job Set(4) {'i', 'love', 'my', 'job'}
  */
  console.log(value, key, currentSet)
  // 这里的this指向window
  console.log(this)
}, this)

结合这段 JS 代码,来描述下 SetforEach 方法的使用:

  • callback
    1. value
    2. key 键。但由于集合对象没有索引,也就是没有 key,这里会与 value 相等。这是为了看起来与数组的 forEach 方法使用一致。
    3. currentSet 当前遍历的 Set 集合。
  • thisArg
    • 如果提供了一个 thisArg 参数给 forEach 函数,则参数将会作为回调函数中的 this 值。否则 this 值为 undefined。回调函数中 this 的绑定是根据函数被调用时通用的 this 绑定规则来决定的。

7-1-4.WeakSet

在讨论 WeakSet 之间,我们需要先了解下垃圾回收

js
// 当我们声明变量时 变量与目标对象会建立引用关系
var obj = {
  name: 'yxp'
}
// 当我们打破建立的引用关系 那么{ name: 'yxp' }会处于“孤立无援”的状态 就会被浏览器回收 从内存中清除掉
obj = null

接下来,我们以数组为例:

js
var obj = {
  name: 'yxp'
}
var list = []
list.push(obj)
// 虽然打破了obj与目标对象之间的引用关系 但数组项与目标对象的引用关系依然保留着 所以这时并不会回收清除
obj = null

WeakSet 的情况下:

js
var tom = { name: 'jack' }
var jerry = { name: 'jerry' }
var weakSet = new WeakSet()
weakSet.add(tom)
weakSet.add(jerry)
// 检查
console.log(weakSet.has(tom))
console.log(weakSet.has(jerry))
// 将tom的引用删除
tom = null
// 此时weakSet中也不会再继续保存tom tom会被垃圾回收机制清除  但由于我们无法确定浏览器对于该机制的具体执行时机 所以下列代码有可能依然是true 但按正常推断来说 应该是false
console.log(weakSet.has(tom))

总结:

  1. Set 类似,但是我们只能向 WeakSet 添加对象(而不能是原始值)。
  2. 对象只有在其它某个(些)地方能被访问的时候,才能留在 set 中。
  3. Set 一样,WeakSet 支持 addhasdelete 方法,但不支持 sizekeys()
  4. WeakSet 不支持迭代。不能使用 forEach

7-2.Map

Map 是一种储存着许多键值对的有序列表。

其中的键名和对应的值支持所有的数据类型。

7-2-1.Map的创建

js
var map = new Map()
// 1.添加元素
map.set('id', 19)
map.set('name', 'yxp')
// 重复添加的话 不会起作用
map.set('name', 'yxp')
// 相比 Set, Map的元素我们可以单个访问
console.log(map.get('id'))
// 2.移除元素
map.delete('name')
// 3.是否包含某一元素
console.log(map.has('id'))
console.log(map.has('name'))
// 4.清空集合
map.clear()

7-2-2.Map与数组

创建 Set 时,可以利用数组进行初始化设置。

而对于 Map,我们也可以使用数组(二维数组)。

js
var map = new Map([['id', 19], ['name', 'yxp'], [{}, '空对象']])
console.log(map)

之所以是二维数组,是因为 Map 的键值要支持所有数据类型。只有在数组中,才能保留这种特性。

如果是对象键值对的方式,键只会是字符串类型。

7-2-3.Map的遍历

Set 的遍历方式相同,Map 也有 forEach 方法。

js
var map = new Map([['id', 19], ['name', 'yxp']])
var thisArg = {
  description: '这个对象是thisArg'
}
map.forEach(function (item, index, currentMap) {
  console.log(item, index, currentMap)
  console.log(this)
}, thisArg)

7-2-4.WeakMap

WeakSet 类似,WeakMap 也可以有效的解决的内存泄漏的问题。

js
var tom = { name: 'Tom' }
var jerry = { name: 'Jerry' }
var weakMap = new WeakMap()
// 支持 set get has delete,不支持clear size forEach
weakMap.set(tom, 'Tom')
weakMap.set(jerry, 'Jerry')
console.log(weakMap)
// 将引用清除
tom = null
// 检测是否还存在
console.log(weakMap.has(tom))

总结:

  1. Map 类似,但是我们只能向 WeakMap 添加对象(而不能是原始值)。
  2. 对象只有在其它某个(些)地方能被访问的时候,才能留在 map 中。
  3. Map 一样,WeakMap 支持 setgethasdelete 方法,但不支持 size
  4. WeakMap 不支持迭代。不能使用 forEach

本章参考文章