ES6-----Set之数据去重,Map之数据存储

63 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

目录

  1. 不重复集合 Set WeakSet
  2. 键值对集合 Map WeakMap
  3. 练习

Set

Set对象,类似数组

  • Set本身是一个构造函数
  • Set对象的实例属性和实例方法
  • Set使用场景: 数据去重
  • Set遍历
  • Set判断数据是否重复,类似 === 全等,全等的数据不能重复添加,NaN是个例外,Set将NaN视为相同;
  • 添加目标是表达式时,会先运算,再以结果作为Set成员添加进去;
 const demo = new Set()
 
 typeof(demo)
 
 // `Set`本身是一个构造函数
 // `Set`函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数
 new Set(document.querySelectorAll('div'))
 
 function demo(){
     new Set(arguments)
 }
 
 
 // 实例属性
 demo.size
  
  
 // 实例方法
 demo.add({})
 demo.add({})  // 不相等
 
 demo.add([])
 demo.add([]) // 不相等
 
 demo.add(NaN)
 demo.add(NaN) // 相等
 
 demo.add(1) 
 demo.add('1') // 不相等
 
 demo.add(null)
 demo.add(null) // 相等
 
 
 demo.add(undefined)
 demo.add(undefined) // 相等
 
 demo.add(1 == '1')
 demo.add(1 == 1)
 demo.add(true)   // 都是true, 相等,保存最终值false
 demo.add(1 === '1')
 demo.add(false)   // 都是false, 相等,保存最终值false
 
 demo.add('')   // 保存空字符
 
  
 demo.add((1,2,3))  // 保存 3
 
 
 demo.has({})
 demo.has(1 == '1')
 
 
 demo.delete('')
 demo.clear()
 
// 转数组
Array.from(demo);
[...demo]

//数组去重
Array.from(new Set([1,1,2,2,3,4]));

// set 能满足
遍历顺序就是插入顺序, 因为Set只能通过add或者初始化时添加,而普通数组有多中添加方法,可改变元素index。

const arr = [2,3,4]
** `keys()``values()``entries()` **

Object.keys(arr)
Object.values(arr)
Object.entries(arr)


demo.keys()
demo.values()
demo.entries()

for (let x of demo) {
  console.log(x);
}

demo = new Set([NaN, [], {}, null, undefined, 1, '1', ()=>{}, '', ' '])
demo.forEach((value, key) => console.log(key, key == value)) // 第一个返回false, 其余都是true

 
[...demo]
// `...`内部使用`for...of`循环,所以也可以用于 Set 结构
 

WeakSet

  • WeakSet 是一个构造函数
  • WeakSet对象实例方法;
  • WeakSet的元素只能是对象,不论是普通对象还是方法对象;
  • 处理对象,任何类型的数据都不能成为WeakSet的成员,包括Symbol类型 和 null;
// 构造函数
// 任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数

// WeakSet 的成员只能是对象

let ws = new WeakSet()

typeof(ws)

const b = [1,2]
ws.add()

ws = new WeakSet(b)
ws.add(b)

// 实例方法

ws.add({})
ws.delete(b)
ws.has(b)


// 弱连接
// 不能遍历,因为是弱映射,不参加内存回收,所以指不定什么时候,数据就消失了
(function(){
    var a = [1]; 
    demo4.add(a); 
    console.log(ws)
})()
// 匿名函数执行完,立即销毁,函数作用域内的a变量也消失,ws存的数据也就消失了
console.log(ws)

Map

补充对象取值

// 补充 对象取值
const person = {
        name: 'cc'
}
person.name // 内部转换 person.name ===> person['name'] ==》 拿到键名为'name'的键值

// 普通对象
const p = {name: 'cc'}
const obj = {}
obj[p] = 'name'  
obj[p] == obj['[object Object]']
// obj[p] ===> obj[p.toString()] ==>  obj['[object Object]'] ===》 实际上 存的键名是'[object Object]'

Map知识

  • Map键值对的集合,键名可以是对象;键名的不重复规则和set的不重复规则一样;
  • 全等的键名名不能重复添加,NaN是个例外,虽然NaN!==NaN,但Map将NaN视为相同;
  • Map作为构造函数
  • 属性和实例方法;
  • 遍历方法;
  • 使用场景: 数据存储
  • Map Set 数组 Iterator Json相互转换;
// 键值集合
// 对象类型键名,必须是是同一个对象,否则,被当多两个键名
const objKey = [1,2,3]
objKeyCopy = objKey
// objKey 和 objKeyCopy 是同一个键名
// objKey 和 [1,2,3] 不是同一个键名


// 构造函数
// 参数: 不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构
map1 = new Map([
  ['name', '张三'],
  ['title', 'Author']
]);

// 非数组,但具有Iterator接口
new Map( new Set([['foo', 1],['bar', 2]]) )


// 属性
const map = new Map()
map.size // 类似数组的arr.length


// 实例方法
map.set(key, value)

map.set('key', 1)
//  链式写法
map.set(1, 'a').set(2, 'b').set(1, 'c')
// 同一个键名重复赋值,后值覆盖前值;


map.get(key)  // 返回value, 找不到返回undefined

map.has(key)  // true false

map.delete(key) //  true false

map.clear()

// 遍历方法
map.keys()
map.values()
map.entries()
map.forEach((value, key, map)=>{})
forof

typeof map.keys() // 'object'
demo.keys() instanceof Array  // false
demo.keys().map() // TypeError: demo.keys(...).map is not a function
// 返回值类型不知数组,需要转换为数组,才能使用数组方法;



// 数据结构转换
[...map]  // map ===》 Array
new Map(Array)  //  Array ===》 map
map.forEach((value, key, map)=>{obj[key] = value})  //  map ===》 Object
new Map(Object.entries(Object)) //  // Object ===》  map
JSON.stringify(数组/对象) map ===》数组/对象 ===》 JSON
toMap(JSON.parse(JSON))  JSON ===》 数组/对象 ===》 map

WeakMap

  • 弱关联集合;只有键名弱关联,键值仍是正常引用
  • 类似Map,不同点:WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名;
  • 键名不参与垃圾回收机制;
  • 实例方法;
// 弱应用,键名随时可能消失,所以
// 除了以下四个方法,其他map的方法都不能用;
get()
set()
has()
delete()

演练playground

- 添加数据

// Set
const demo = new Set()
const arr = [1,2,3]

demo.add([1,2,3])
demo.add(arr)
demo.add(1 - '0')
demo.add(1 + '0')
demo.add(Infinity/0)
demo.add(Infinity/-0)
demo.add(Infinity/-9)

//Map
const demo2 = new Map()
demo2.set(undefined, 1)
demo2.set(null, 1)
demo2.set(false, 1)
demo2.set(true, 1)
demo2.set(NaN, 1)
demo2.set((1,2,3), 1)
demo2.set(-0, 1)
demo2.set(0, 1)
demo2.set('', 1)

- 判断是否是Set Map数据类型

// instanceof
demo instanceof Map
demo instanceof Set

// Object.prototype.toString.call()
Object.prototype.toString.call(demo)  // '[object Set]' 或 '[object Map]‘

//constructor
demo.constructor === Map
demo.constructor === Set