一、ECMAScript 5 中的 Sets 和 Maps
在 ECMAScript 5 中,通常使用对象属性来模拟 set 和 map 数据类型:1
2
3
4
5
6
7var set = Object.create(null)
set.foo = true
if (set.foo) {
// code to execute
}
用对象属性作为 set 中的非重复键值,将值设置为 true 表明其存在性。
1 | var map = Object.create(null) |
不同于 set,map 常常需要获取其中保存的数据,而不仅仅用于检查 key 是否存在。
存在的问题
用对象作为 set 和 map 适用于简单的场景,在某些情况下对象属性会显露出一定的局限性。
比如所有的对象属性都必须是字符串类型,因此同一个对象中绝不能包含多个(转换成字符串后)一致的键。1
2
3
4var map = Object.create(null)
map[5] = "foo"
console.log(map["5"]) // foo
数字类型的键 5
实际上在内部会被转换为字符串 "5"
,因此 map[5]
和 map["5"]
指向的是同一个值。
又比如:1
2
3
4
5
6var map = Object.create(null)
var key1 = {}
var key2 = {}
map[key1] = "foo"
console.log(map[key2]) // foo
上面代码中的 map[key1]
和 map[key2]
也是指向同一值的。因为对象 key1
和 key2
转换为字符串后的值同为 "[object Object]"
。
二、ECMAScript 6 中的 Sets
ECMAScript 6 中添加了 Set 类型,即一个包含不重复的有序值的列表。1
2
3
4
5
6
7
8
9
10
11
12
13let set = new Set()
set.add(5)
set.add("5")
console.log(set) // Set { 5, '5' }
let set2 = new Set()
let key1 = {}
let key2 = {}
set2.add(key1)
set2.add(key2)
console.log(set2.size) // 2
使用 set 去重:1
2
3
4
5
6
7
8
9
10
11
12let set = new Set()
set.add(5)
set.add("5")
set.add(5)
console.log(set) // Set { 5, '5' }
let set2 = new Set([1, 2, 3, 4, 5, 5, 5, 5])
console.log(set2) // Set { 1, 2, 3, 4, 5 }
console.log(set2.has(2)) // true
console.log(set2.has(6)) // false
forEach:1
2
3
4
5
6
7
8
9
10
11let set = new Set([1, 2])
set.forEach(function(value, key, ownerSet) {
console.log(key + " " + value)
console.log(ownerSet === set)
})
// 1 1
// true
// 2 2
// true
如果需要在 forEach()
的回调函数中使用 this
,可以将 this
作为 forEach()
的第二个参数传递:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16let set = new Set([1, 2])
let processor = {
output(value) {
console.log(value)
},
process(dataSet) {
dataSet.forEach(function(value) {
this.output(value)
}, this)
}
}
processor.process(set)
// 1
// 2
Set 与 Array 的互换:1
2
3
4
5
6
7let set = new Set([1, 2, 3, 3, 3, 4, 5])
console.log(set)
// Set { 1, 2, 3, 4, 5 }
let array = [...set]
console.log(array)
// [ 1, 2, 3, 4, 5 ]
1 | function removeDuplicates(items) { |
三、ECMAScript 6 中的 Maps
1 | let map = new Map() |
可以使用对象作为 Map 中的键,这些键不会转换为另一种形式,且都是唯一的:1
2
3
4
5
6
7
8
9let map = new Map()
let key1 = {}
let key2 = {}
map.set(key1, 5)
map.set(key2, 42)
console.log(map.get(key1)) // 5
console.log(map.get(key2)) // 42
Map 方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17let map = new Map()
map.set("name", "Nicholas")
map.set("age", 25)
console.log(map.size) // 2
console.log(map.has("name")) // true
console.log(map.get("name")) // Nicholas
map.delete("name")
console.log(map.has("name")) // false
console.log(map.get("name")) // undefined
console.log(map.size) // 1
map.clear()
console.log(map.has("age")) // false
console.log(map.get("age")) // undefined
console.log(map.size) // 0
forEach:1
2
3
4
5
6
7
8
9
10let map = new Map([["name", "Nicholas"], ["age", 25]])
map.forEach(function(value, key, ownerMap) {
console.log(key + " " + value)
console.log(ownerMap === map)
})
// name Nicholas
// true
// age 25
// true