Symbol
- Symbol 是基本数据类型
- length 为 0
Symbol('foo')
每次都会创建新的 symbol 类型
for in
无法遍历出Symbol
属性
for(let key of Object.keys(obj))
无法遍历出Symbol
属性
for(let key of Object.getOwnPropertySymbols(obj))
只能遍历出Symbol
属性
for(let key of Reflect.ownKeys(obj))
既能遍历出普通属性,也能遍历出Symbol
属性
let s1 = Symbol('foo')
let s2 = Symbol('foo')
console.log(s1)
console.log(s1 === s2) // false
console.log(s1.description)
/*
Symbol(foo)
false
foo
*/
Symbol.for
创建全局共享 symbol
从全局 symbol 注册表查找 key, 如果找到了, 则返回; 如果未找到, 则创建
let s3 = Symbol.for('foo')
let s4 = Symbol.for('foo')
// Symbol.for() 在全局中定义,s4 重复定义相同的值就会指向已定义的 s3
console.log(s3 === s4) // true
Symbol.keyFor()
如果全局注册表中查找到该symbol,则返回该 symbol 的 key 值,返回值为字符串类型。否则返回
undefined
// 创建的 symbol 不是全局的
let s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefined
// 创建全局的 symbol
let s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2)) // 'foo'
消除魔术字符串
- 此时的
Triangle
为魔术字符串,多次出现形成强烈的耦合
const shapeType = {
triangle: Symbol(),
circle: Symbol()
}
function getArea(shape) {
let area = 0
switch (shape) {
case shapeType.triangle:
area = 1
break
case shapeType.circle:
area = 2
break
}
return area
}
getArea(shapeType.triangle)
Set
- 值唯一
- 数据结构为键值对形式,键和值相等
常用方法
let s = new Set([1, 2, 3])
// 增加数据
s.add(4).add(5)
// 删除数据
s.delete(2)
// 清空数据
s.clear()
// 是否包含某个值,返回 Boolean
s.has(5)
// Set 长度
s.size
遍历
let s = new Set([1, 2, 3])
for(let item of s) {
console.log(item)
}
for(let item of s.keys()) {
console.log(item)
}
for(let item of s.values()) {
console.log(item)
}
for(let item of s.entries()) {
console.log(item)
}
/* entries
[ 1, 1 ]
[ 3, 3 ]
[ 4, 4 ]
[ 5, 5 ]
*/
应用场景
数组去重
// 数组去重
let arr = [1, 2, 3, 4, 2, 3]
let s = new Set(arr)
console.log(s) // Set { 1, 2, 3, 4 }
合并去重
// 合并去重
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])
console.log(s) // Set { 1, 2, 3, 4, 5, 6 }
// Set 转换为数组 与 Array.from(s) 等价
console.log([...s]) // [ 1, 2, 3, 4, 5, 6 ]
求交集
// 求交集
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
console.log(result) // Set { 2, 3, 4 }
差集
// 差集
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let arr3 = new Set(arr1.filter(item => !s2.has(item)))
let arr4 = new Set(arr2.filter(item => !s1.has(item)))
console.log([...arr3, ...arr4])
WeakSet
- 只能够存储对象
- 无法遍历
WeakSet
中的对象都是弱引用
Map
- 对象的
key
只能使用string
和symbol
,map
的key
可以为任意类型
key
重复,后设置的值将覆盖掉前面的值
常用方法
let m = new Map()
let obj = {
name: 'imooc'
}
// 设置值
m.set(obj, 'es')
console.log(m) // Map { { name: 'imooc' } => 'es' }
// 获取值
m.get(obj)
// 删除值
m.delete(obj)
// 是否包含某个值,返回 Boolean
m.has(obj)
// 长度
m.size
// 数组第一个元素为键,第二个元素为值
let map = new Map([
['name', 'ye'],
['age', 18]
])
console.log(map) // Map { 'name' => 'ye', 'age' => 18 }
遍历
// 遍历
map.forEach((value, key) => console.log(value, key))
for(let [key, value] of map) {
console.log(key, value)
}
for(let key of map.keys()) {
console.log(key)
}
for(let value of map.values()) {
console.log(value)
}
for(let [key, value] of map.entries()) {
console.log(key, value)
}
应用场景
- 对于频繁修改的场景,
map
性能比对象高
- 能使用对象的场景,都可以使用
map
WeakMap
- 键名只支持引用数据类型(数组、对象等)
- 不支持遍历
- 不支持
clear()
- 不支持
size
属性
- 弱引用