🚜

ES6

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只能使用stringsymbolmapkey可以为任意类型
  • 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属性
  • 弱引用