(四) Set和Map

1. Set

1.1 Set的基本使用

Set 是es6新增的引用类型的数据结构, 其本身也是一个构造函数, 可以接收一个数组作为参数

特点: 元素的值是唯一的, 不存在重复元素

基本使用

let set = new Set([1, 2, 2, 3, 1, 5])
console.log(set)	// Set(4) {1, 2, 3, 5}

// 将Set转换成数组
let arr = [...set]

利用这一特性, 也为数组去重提供了新方法

let arr = [1, 2, 2, 3, 1, 5]
arr = [...new Set(arr)]
console.log(arr)    // [1, 2, 3, 5]

此外, 我们还可以利用 Array.from() 将Set转换成数组

let set = new Set([1, 2, 3])
console.log(Array.from(set)) // [1,2,3]

那么Set保证内部元素不重复的机制是什么 ?

  • 类似于 === 比较

注意这里说的是类似, 因为存在一个特殊的值 NaN not a number

console.log(typeof NaN)  // 'number'
console.log(NaN == NaN)  // false
console.log(NaN === NaN) // false

NaN 与任何值都不相等, 包括它本身, 但是再Set中的判断却不是这样

console.log(new Set([NaN, NaN]))  // Set(1) {NaN}

在Set内部, 将NaN和NaN当作是全等的

另外, 在Set内部, 像1 和 '1', {} 和 {} 都是不相等的 (遵循一般规则)

1.2 Set的实例属性和方法

属性: Set.prototype.size 返回实例的元素总数

let set = new Set([1, 2, 3, 4])
console.log(set.size) // 4

方法:分为操作方法和遍历方法

操作方法:

  • add(value) : 添加值
  • has(value): 判断是否有value这个元素, 返回布尔值
  • delete(value): 删除值, 返回布尔值, 表示删除成功与否
  • clear(): 清空
let set = new Set()

set.add(1).add(2)
console.log(set) // {1,2}

console.log(set.has(1)) // true
console.log(set.has(3)) // false

set.delete(2)
console.log(set)  // {1}

set.clear()
console.log(set)  // {}

遍历方法:

@注意: Set遍历的顺序是插入的顺序

  • forEach(value, key, set)
  • keys()
  • values()
  • entries()
let set = new Set([100, 200, 300])

set.forEach((v, k) => {
  console.log(v, k);
})
/* 
  100 100
  200 200
  300 300
*/
// 值和键是相同的

1.3 案例

利用Set...实现数组的 并集、交集、差集

let arr1 = [1, 2, 3]let arr2 = [4, 3, 2]// 并console.log(new Set([...arr1, ...arr2]))  // {1,2,3,4}// 交let set1 = new Set(arr1)let set2 = new Set(arr2)console.log(new Set([...arr1].filter(item => set2.has(item))))   // {2,3}// 差console.log(new Set([...arr1].filter(item => !set2.has(item))))   // {1}

2. Map

2.1 Map的基本使用

Map 是es6新增的引用类型的数据结构, 其本身也是一个构造函数, 可以接收一个数组作为参数

  • 参数数组的元素是 元素存在键值对映射关系的数组

基本使用

let map = new Map([['key', 'value']])console.log(map)  // Map(1) {"key" => "value"}// 将Map转成数组let arr = [...map]

Map的出现解决了es5中对象的缺陷:

  • 传统的Object提供的键值对组合, 键只能是 字符串, 而Map中的键允许是各种类型
// Objectlet obj = {}obj[{ id: 1 }] = 100console.log(obj)  // {[object Object]: 100}// Maplet o1 = { a: 1 }let map = new Map()map.set(o1, '123')console.log(map)		// Map(1) {{…} => "123"}console.log(map.get(o1))  // 123

可以利用 set(key, value) 为Map添加新成员

利用 get(key) 获取value

@注意:

  • 与Object一样, 属性名相同的话, 后面的会覆盖前面的
  • 但是, Map判断属性名是否相同是 根据内存地址是否相同来作为依据的
let k1 = {}let k2 = k1		// k2定义为k1的引用let map = new Map([  [k1, 1],  [k2, 2]])console.log(map)  // Map(1) {{…} => 2} // 只存在一个成员, 却可以通过另外的属性名获取到值// 因为k2时是对k1的引用, 本质上还是对k1的查找console.log(map.get(k1))	// 2console.log(map.get(k2))	// 2
let k1 = {}let k2 = {}let map = new Map([  [k1, 1],  [k2, 2]])console.log(map)  // Map(2) {{…} => 1, {…} => 2}// 存在两个成员, 而且取到的值各不相同// 因为 {} 与 {} 是两个不同的对象 => 内存地址不同console.log(map.get(k1))  // 1console.log(map.get(k2))  // 2

2.2 Map的实例属性和方法

属性: size属性, 返回实例的成员总数

操作方法:

  • set(key,value) : 添加键值对, 如果key已经存在, 则更新覆盖
  • get(key): 获取key对应的值
  • has(key): 判断key是否在Map中, 返回一个布尔值
  • delete(key)
  • clear()

遍历方法:

@注意: Map遍历的顺序是插入的顺序

  • forEach(value, key, set)
  • keys()
  • values()
  • entries()
let map = new Map([  ['k1', 10],  ['k2', 20]])map.forEach((value, key) => {  console.log(value, key)})/*  10 "k1"   20 "k2"*/
posted @ 2021-08-02 22:36  只猫  阅读(78)  评论(0编辑  收藏  举报