美文网首页
Set 和 Map

Set 和 Map

作者: 示十 | 来源:发表于2020-01-17 16:15 被阅读0次

Set

介绍

类似数组,新的数据结构,成员的值唯一

可以添加数组、类数组、字符串(或者说是具有 iterable 接口的其他数据结构)作为参数

const set = new Set();
const set = new Set([1,2,3]);
const set = new Set('abcdec');

值的比较算法

使用Same-value-zero equality 算法进行比较,类似 ===

二者区别是对于 NaN 值的比较:前者会认为NaN是相等的,后者 NaN === NaN // false

两个对象,即使是空对象也是不相等的 {}

总结:Set 认为基础数据类型总是相等的,而复杂数据类型总不相等

属性和方法

属性:

size: 返回成员总数

方法:

  • 操作方法
方法名称 说明 返回值
add() 添加某个值 返回 Set 结构本身
delete() 删除某个值 返回一个布尔值
has() 是否包含某个值 返回一个布尔值
clear() 清除结构所有成员 无返回值
const set = new Set();
console.log(set.size); // 0
set.add(1);
set.add(2);
set.add(3);
console.log(set.size); // 3
set.delete(2);
console.log(set.size); // 2
console.log(set.has(3)); // true
console.log(set.has(2)); // false
set.clear();
console.log(set.size); // 0

Array.from 可以将 Set 结构转成数组

const set = new Set([1, 2, 3, 4, 3, 5, 6, 6]);
const arr = Array.from(set);
console.log(arr); // [1, 2, 3, 4, 5, 6]
  • 遍历方法

遍历顺序是插入顺序,使用 Set 保存一个回调函数列表,调用时可以按照添加顺序调用

方法名称 返回值
keys() 返回键名的遍历器
values() 返回键值的遍历器
entries() 返回所有成员的遍历器
forEach() 遍历 Map 所有成员
const set = new Set(['red', 'green', 'blue']);

for (const item of set.entries()) {
    console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

可以看到 Set 结构的键值为同一个值,所以,keys() 和 values() 方法返回的是同一个值

for (const item of set.keys()) {
    console.log(item);
}
// red
// green
// blue

for (const item of set.values()) {
    console.log(item);
}
// red
// green
// blue

forEach() 方法可以操作 Set 成员:

const set = new Set(['red', 'green', 'blue']);

set.forEach((value, key, set) => {
    console.log(`key: ${key}; value: ${value};set: ${set};`)
})

// key: red; value: red;set: [object Set];
// key: green; value: green;set: [object Set];
// key: blue; value: blue;set: [object Set]; 

遍历的作用

  1. 去重

可以使用扩展运算符去除数组重复成员

const set = new Set(['red', 'green', 'blue']);

// 将 Set 转成数组
let arr = [...set]; //  ["red", "green", "blue"]

// 去除数组重复成员
const numArr = [1, 2, 2, 3, 4, 5, 6, 5, 6];
let unique = [...new Set(numArr)]; // [1, 2, 3, 4, 5, 6]
  1. 给 Set 数据结构使用数组方法
let set = new Set(['red', 'green', 'blue']);

set = new Set([...set].map(x => x + 'ing')); // Set(3) {"reding", "greening", "blueing"}
set = new Set([...set].filter(x => x.length > 3)); // Set(2) {"green", "blue"}

另一个例子:

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

<!-- 合并数组 -->
let union = new Set([...set1, ...set2]); // Set(5) {1, 2, 3, 5, 6}
<!-- 并集 -->
let intersect = new Set([...set1].filter(x => set2.has(x))); // Set(2) {2, 3}
<!-- 交集 -->
let diff = new Set([...set1].filter(x => !set2.has(x))); // Set(1) {1}

WeakSet

  1. WeakSet 的成员只能是对象,不能是其他类型的值
  2. WeakSet 中的对象是弱引用(关于引用的相关知识查看文末提示),gc 随时可能把引用清除,所以,ES6 规定 WeakSet 不可遍历;适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
let ws = new WeakSet([1, 2, 3]); // error 不能将类型“number”分配给类型“object”
let ws1 = new WeakSet([[1, 2], [3]]); // ok

方法

方法名称 说明 返回值
add() 添加某个值 返回 WeakSet 结构本身
delete() 清除实例指定的成员 返回一个布尔值
has() 是否包含某个值 返回一个布尔值
const obj = {};
const foo = {};

let ws = new WeakSet();
ws.add(obj);
ws.add(foo);

ws.delete(foo); // true
ws.has(foo); // false

用途

  1. 存储 DOM 节点,而不必担心这些节点从文档移除时,会引发内存泄漏
  2. 由于垃圾回收机制不存储 foos 成员的引用,所以删除实例的时候,不会引发内存泄漏
const foos = new WeakSet();
class  Foo {
    constructor() {
        foos.add(this);
    }
    methods() {
        if (!foos.has(this)) {
            throw new TypeError('Foo.prototype.methods 只能在 Foo 的实例上调用!')
        }   
    }
}

Map

一种“值-值”的数据结构,比 Object “字符串-值”的数据结构更为完善的 Hash 结构。

存值方式和 Set 一样,对于基础数据类型,只要严格相等,Map 就认为是一个键;对于复杂数据类型,只要内存地址不同,就是不同的键。

属性和方法

属性:

size: 返回成员总数

方法:

  • 操作方法
方法名称 说明 返回值
set() 添加某个值 返回 Map 结构本身
get() 获取某个值 返回 Map 键对应的值
delete() 删除某个值 返回一个布尔值
has() 是否包含某个值 返回一个布尔值
clear() 清除结构所有成员 无返回值
  • 遍历方法

遍历顺序是插入顺序

方法名称 返回值
keys() 返回键名的遍历器
values() 返回键值的遍历器
entries() 返回所有成员的遍历器
forEach() 遍历 Map 所有成员

与其他数据结构互相转换

  1. Map 转数组
const myMap = new Map()
  .set(true, 7)
  .set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
  1. 数组转 Map
new Map([
  [true, 7],
  [{foo: 3}, ['abc']]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ['abc']
// }
  1. Map 转对象
function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

const myMap = new Map()
  .set('yes', true)
  .set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
  1. 对象转 Map
function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}

objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}
  1. Map 转 JSON

Map 的键名都是字符串:

function strMapToJson(strMap) {
  return JSON.stringify(strMapToObj(strMap));
}

let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'

Map 的键名都是非字符串

function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}

let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
  1. JSON 转 Map

所有键名都是字符串

function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}

jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}

整个 JSON 是一个数组,每个数组成员又是一个由两个成员的数组

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
}

jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}

WeakMap

方法名称 说明 返回值
set() 添加某个值 返回 Map 结构本身
get() 获取某个值 返回 Map 键对应的值
delete() 删除某个值 返回一个布尔值
has() 是否包含某个值 返回一个布尔值

WeakMap 的应用场景

  1. DOM 节点作为键名
let myEle = document.getElementById('logo');
let myWm = new WeakMap();

myEle.set(myEle, { timesClicked: 0 });

myEle?.addEventListener('click', () => {
    let logoData = myWm.get(myEle);
    logoData.timesClicked++;
}, false);
  1. 部署私有属性
const _counter = new WeakMap();
const _action = new WeakMap();

class Countdown {
    constructor(couter, action) {
        _counter.set(this, couter);
        _action.set(this, action);
    }
    dec() {
        let counter = _counter.get(this)
        if (counter < 1) return;
        counter--;
        _counter.set(this, counter);
        if (counter === 0) {
            _action.get(this)();
        }
    }
}

const ct = new Countdown(2, () => console.log('Down'));
ct.dec();
ct.dec();
// Down

引用来源1

java 中的引用

强引用:就像是老板(OOM)的亲儿子一样,在公司可以什么事都不干,但是千万不要老是占用公司的资源为他自己做事,记得用完公司的妹子之后,要让她们去工作(资源要懂得释放) 不然公司很可能会垮掉的。

软引用:有点像老板(OOM)的亲戚,在公司表现不好有可能会被开除,即使你投诉他(调用GC)上班看片,但是只要不被老板看到(被JVM检测到)就不会被开除(被虚拟机回收)。

弱引用:就是一个普通的员工,平常如果表现不佳会被开除(对象没有其他引用的情况下),遇到别人投诉(调用GC)上班看片,那开除是肯定了(被虚拟机回收)。

虚引用:这货估计就是个实习生跟临时工把,遇到事情的时候想到了你,没有事情的时候,秒秒钟拿出去顶锅,开除。

引用来源2:阮一峰 ES6 教程

相关文章

  • ES6

    Symbol Set和Map Set Map Proxy get() set() apply() Reflect ...

  • Java Map,List,Set,String[]之间的转换

    Map和List map.values转list: Map和set map转set(主要用于迭代遍历) set转m...

  • Map 、Set&Object、Array

    1. Map和Set是什么? 2. Map和Set与Object和Array有什么区别,为何引入Map和Set? ...

  • 面试题解答

    Set 和Map 的方法 Set sizeaddforeachhasdeleteclear Map gethass...

  • java开发工程常用的数据结构(集合)

    List Map Set list,set,map对比 总结: Vector和ArrayList vector是线...

  • ES6新增Map和Set数据类型

    Map和Set Map 和 Set 是 ES6 标准新增的数据类型 Map JavaScript的对象(Objec...

  • Map和Set

    Map:一组键值对的结构,具有极快查找速度有has(判断是否有该键值对)get(得到对应键值)set(设置键值对)...

  • Set和Map

    Set和Map Set实例属性Set.prototype.constructor 构造函数,默认SetSet.pr...

  • Set和Map

  • Map和Set

    Map Map是一组键值对的结构,具有极快的查找速度。 初始化Map方法: 一个key只能对应一个value,所以...

网友评论

      本文标题:Set 和 Map

      本文链接:https://www.haomeiwen.com/subject/xiaczctx.html