ES6之 Map、Set 数据结构

74 阅读3分钟

Set 数据结构

Set 数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值。

let set = new Set()

1. 实例属性

  • constructor 默认是 Set 函数
  • set.size 获取长度
  • 构造函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数
    • new Set([1,2,3]) // Set(3){1,2,3}
    • new Set(document.querySelectorAll('div'))

2. 操作方法

  • set.add(1).add(2)
  • set.add([1,2,3])
  • set.has('a')
  • set.delete('a')
  • set.clear()

3. 遍历方法

  • 顺序:遍历顺序就是插入顺序。比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用
  • 没有键名,只有键值,keys()和 values()行为一致
  • set.keys() // 返回遍历器对象 SetIterator{1,2}
  • set.values()
  • set.entries() // 返回键值对的遍历器对象,且键和值相等
  • set.forEach()

🌰

// Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。
let set = new Set(['red', 'green', 'blue']);

for (let x of set) {
  console.log(x); // 'red', 'green', 'blue'
}

for(let i in set) {
    console.log(i) // undefined
}

4. Set 结构与数组转换

  • 扩展运算符(...)内部使用 for...of 循环,所以也可以用于 Set 结构

  • 转换后,数组的 map 和 filter 方法可以间接用于 Set 了

    • [...new Set(set)]
    • Array.from(set)
  • 去重 (数组/字符串,内部使用 "===" 全等进行判断)

    • [...new Set(arr)]
    • [...new Set('abbc')].join('')
  • 实现并集(Union)、交集(Intersect)、差集(Difference) 理解:求并集时 set 解构比较好用,求交集时其实就是在操作数组了。

🌰

let set1 = new Set([1,2,3])
let set2 = new Set([4,3,2])

// 并集(合并且去重)
let union = new Set([...set1,...set2]) // Set{1,2,3,4}

// 交集(公共部分)
let arr = [...set1].filter((item)=>{
   return set2.has(item)
})
arr; // [2,3]

//(a 相对于 b 的)差集
let difference =[...set1].filter(x => !b.has(x)) // [1]


Map 数据结构

背景:

  1. JS Object 对象本质是键值对的集合(Hash 结构),只能用字符串当做键。ES6 Map 数据结构解决了这个问题。
  2. Map 数据结构类似于 Object,但键包括各种类型。

let map = new Map()

理解:

  1. Hash 结构
  2. 如果只是需要普通键值对的对象,Object 即可满足使用

1. 实例属性

  • 作为构造函数,Map 可以接受一个"数组"作为参数。(或者任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构)
  • 数组的"成员"是一个个"表示键值对的数组"(此处容易记错!!)
let map = new Map([
  ['name','张三'],
  ['title','author']
  ]) // Map(2){'name'=>'张三','title'=>'author'}

// 相当于
const items = [
  ['name', '张三'],
  ['title', 'Author']
];
const map = new Map();
items.forEach(
    ([key,value])=> map.set(key,value)
)
  • map.size // 2

2. 操作方法

  • map.set(o:'content') //可以采用链式写法
  • map.get(o) // 'content'
  • map.has(o) // true
  • map.delete(o) // true
  • map.clear() //没有返回值

说明:

  • 对同一个键多次赋值,后面的值将覆盖前面的值(简单类型)
  • 只有对同一个对象的引用,Map 结构才将其视为同一个键(解决了同名属性碰撞(clash)的问题)

进度:实例的属性和操作方法 es6.ruanyifeng.com/#docs/set-m…

3. 遍历方法

  • 遍历顺序就是插入顺序
  • map.keys()
  • map.values()
  • map.entries()
  • map.forEach()

4. Map 与数组相互转换

  1. Map 转数组 扩展运算符(...):Map 本身也没有 map 和 filter 方法,转换成数组后,使用数组的 map 方法、filter 方法,可以实现 Map 的遍历和过滤。
[...new Map([  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
])]

// [[1,'one'], [2, 'two'], [3, 'three']]

  1. 数组转 Map 将数组传入 Map 构造函数即可(数组的"成员"是一个个"表示键值对的数组"(此处容易记错!!))
new Map([
  [true, 7],
  [{foo: 3}, ['abc']]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ['abc']
// }

5. Map 与对象相互转换

  1. map 转对象
  • 当 map 的 key 都是字符串时可以实现无损转换
  • 如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
const myMap = new Map()
  .set('yes', true)
  .set('no', false);
strMapToObj(myMap);

function strMapToObj(myMap){
  let obj = Object.create(null); 
  for(let [key,value] of myMap){
    obj[key] = value
  }
  return obj
}
  1. 对象转 Map
let obj = {"a":1, "b":2};
let mapArr = Object.entries(obj); // [['a',1],['b',2]]
let map = new Map(mapArr);

参考:es6.ruanyifeng.com/#docs/set-m…