Set、Map引用数据类型(WeakSet,WeakMap)

1、Map

ES6新增的集合类型(引用数据类型),表示数据的映射关系,map集合数据类型中数据是以键/值的方式存储的.可以使用对象的属性作为键,使用属性来引用值。

1-1 创建Map

使用new关键字来实例一个map

let m = new Map();

console.log(m);
// Map(0) {}

创建时初始化:
传入一个二维数组参数(可迭代对象,内部以数组的方式传入键值)
每个子数组,第一个元素是map对应的key, 第二个元素是map对应的value

let m = new Map([[{}, 222], [{}, '123']]);

console.log(m);
// Map(2) { {} => 222, {} => '123' }

1-2 Map Api

1-2-1 添加映射元素

通过set()方法添加,传入两个参数,第一个传入映射的键,第二个传入映射的值。返回的是该映射集合(意味着可以链式添加)

let m = new Map();

m.set('prop', '值');

console.log(m);
// Map(1) { 'prop' => '值' }

链式添加键值

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

console.log(m);
// Map(3) { 'prop' => '值', 'prop2' => false, 'num' => { id: 13 } }

1-2-2 映射集合长度

使用size属性可以获取到当前集合元素数量

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

console.log(m.size);

1-2-3 获取元素

通过get()方法获取到元素,传入获取目标的key

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

console.log(m.get('prop2'));
// false

1-2-4 删除元素

通过delete()方法删除映射集合中的某个元素,返回删除成功或失败的布尔值

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

m.delete('prop2');
// true

console.log(m.get('prop2'), m.size);
// undefined 2

1-2-5 检测元素是否存在

使用has()方法检测目标元素是否存在,返回检测结果的布尔值

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

m.delete('prop2');
// true

console.log(m.has('prop2'), m.has('num'));
// false  true

1-2-6 清除元素方法

使用clear()方法可以清除所有的元素, 返回清除成功的布尔值

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

m.clear();
// true

console.log(m);
// Map(0) {}

1-3 顺序与迭代

map可以根据插入顺序迭代元素
映射实例会提供(iterator).能够以插入的顺序生成[key, value]形式的数组, 可以通过entries()方法(或者提供的Symbol.iterator)迭代器接口遍历。

let m = new Map();

m.set('prop', '值').set('prop2', false).set('num', {id: 13});

console.log(m.entries === m[Symbol.iterator]);// true

for(let k1 of m.entries()){
    console.log(k1);
    // [ 'prop', '值' ]
    // [ 'prop2', false ]
    // [ 'num', { id: 13 } ]
    // 遍历的属性即对应映射元素的键值对数组
}

for(let k2 of m.keys()){
    console.log(k2);
    // prop
    // prop2
    // num
    // 遍历的属性对应映射元素的键
}

for(let k3 of m.values()){
    console.log(k3);
    // 值
    // false
    // { id: 13 }
    // 遍历的属性对应映射元素的值
}

for(let k4 of m[Symbol.iterator]()){
    console.log(k4);
    // [ 'prop', '值' ]
    // [ 'prop2', false ]
    // [ 'num', { id: 13 } ]
    // 遍历的属性即对应映射元素的键值对数组
}

1-4 与Object对比

  • 内存占用

    浏览器的差异会导致两种存储方式占用的内存占用所不同,不过在给定内存大小的情况下,map比Object多存储大约50%的键值对

  • 插入性能

    插入速度上面 map 和 Object性能大致相同, 但是如果代码涉及大量的插入,建议使用map

  • 查找速度

    差异较小,只包含少量键值对的情况下Object更好

  • 删除性能

    Object 的delete()性能较差,而map的删除delete()性能好,如果数据涉及到大量的删除操作,建议使用map


2、Set

是es6中新增的一种数据类型, 即集合
set是一个引用类型的数据

2-1 创建Set

创建set可以使用new关键字创建

let set = new Set();
// 返回一个空集合
// Set(0) {}

// 创建set时初始化set
// 传入参数(可迭代对象)
// 传入的字符串、数组等会被迭代
let set1 = new Set('123');
console.log(set1);
// Set(3) { '1', '2', '3' }

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

let set4 = new Set({id: 12, uname: 'Tom'});
console.log(set4);// 报错 
//Object参数内部不包含[Symbol.iterable]迭代器接口

// arguments 内部包含有迭代器接口
function sum(){
	let set5 = new Set(arguments);
	return set5;
}

console.log(sum(1,2,3,5));
// Set(4) { 1, 2, 3, 5 }

2-2 Set Api

2-2-1添加集合值

add()方法可用于添加集合值,返回添加完成后的集合实例(说明可以链式添加)

let set = new Set();

set.add('1');
set.add(10);
set.add(true);
set.add({});

console.log(set);
// Set(4) { '1', 10, true, {} }

// 链式添加
let set2 = new Set();

set2.add(1).add('2').add(false).add({id: 1}).add([12]);

console.log(set2);
// Set(5) { 1, '2', false, { id: 1 }, [ 12 ] }

2-2-2 清除集合

clear()方法可清除集合所有值

let set2 = new Set();

set2.add(1).add('2').add(false).add({id: 1}).add([12]);

console.log(set2);
// Set(5) { 1, '2', false, { id: 1 }, [ 12 ] }

set2.clear();
console.log(set2);
// Set(0) {size: 0}

2-2-3 集合长度

size属性可查看当前集合包含值的数量

let set2 = new Set();

set2.add(1).add('2').add(false).add({id: 1}).add([12]);

console.log(set2);
// Set(5) { 1, '2', false, { id: 1 }, [ 12 ] }

console.log(set2.size);
// 5

2-2-4 删除值

delete()方法可删除某个集合元素,返回删除成功或失败的布尔值

let set2 = new Set();

set2.add(1).add('2').add(false).add({id: 1}).add([12]);

set2.delete(false); // true

console.log(set2);
// Set(4) {1, '2', {…}, Array(1)}

2-2-5 检测集合元素是否存在

has()方法可检测某个集合中是否存在某个元素。结果返回布尔值,表示检测到或者找不到

let set2 = new Set();

set2.add(1).add('2').add(false).add({id: 1}).add([12]);

console.log(set2.has(1)); // true
console.log(set2.has('2')); // true
console.log(set2.has(true)); // false

注意:以上案例中添加了如==[12]==, =={id: 1}==这样的元素。在这种情况下检测[12],{id: 1}会返回false

let set2 = new Set();

set2.add(1).add('2').add(false).add({id: 1}).add([12]);

console.log(set2.has([12])); // false

console.log(set2.has({id: 1})); // false

这是因为存入的对象或数组是一个地址值,而参数中要查找数组或对象是另一个地址值,所以查找不到指定元素

解决

let set2 = new Set(),
	obj = {id: 1},
	arr = [12];

set2.add(1).add('2').add(false).add(obj).add(arr);

console.log(set2.has(arr)); // true

console.log(set2.has(obj)); // true

2-3 Set特性

集合:两个范围内的交合部分
这个部分具有唯一性

Set唯一性: set集合内元素是唯一的
set的元素可以是任意类型
set集合是无序的

let s = new Set(['12', 22, true, 22]);

console.log(s, s.size);
// Set(3) {'12', 22, true} 3

2-4 顺序与迭代

Set支持按照顺序迭代, 集合的实例可以提供一个迭代器,能以插入顺序生成集合内容。可以通过values方法即其别名方法keys方法(或者Symbol.iterator属性)取得这个迭代器。

let s = new Set([1, 2, '3', true, 4]);

console.log(s.values === s[Symbol.iterator]); // true
console.log(s.keys === s[Symbol.iterator]); //true

// 拥有迭代器即可迭代
for (let k of s.values()) {
    console.log(k, s.values()[k]);
    // 1 undefined
    // 2 undefined
    // 3 undefined
    // true undefined
    // 4 undefined
}

for (let prop of s.keys()) {
    console.log(prop);
    // 1
    // 2
    // 3
    // true
    // 4
}

for (let p of s[Symbol.iterator]()) {
    console.log(p);
    // 1
    // 2
    // 3
    // true
    // 4
}

// 可以使用forEach相关的api来遍历set集合
s.forEach((value, index) => {
    console.log(value, index);
    // 1 1
    // 2 2
    // 3 3
    // true true
    // 4 4
})

3、WeakMap

ES6新增的’弱映射’, 是map的兄弟类型,api也是map的子集。JavaScript垃圾回收机制对待这种弱类型map有特殊的处理方式。

3-1 创建WeakSeMap

和map类型创建方式一致

let wm = new WeakMap();

注意:传入WeakSet集合的元素必须是Object或者继承自Object类型

3-2 WeakMap Api

3-2-1 添加元素

通过set()方法实现

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakMap
let wm = new WeakMap();

wm.set(obj1, obj1).set(like, like);

console.log(wm);
// WeakMap {{uname: 'Tom', age: 12} => {uname: 'Tom', age: 12}, Array(3) => Array(3)}

3-2-2 删除某个元素

使用delete()方法实现删除某一个元素

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakMap
let wm = new WeakMap();

wm.set(obj1, obj1).set(like, like);

wm.delete(obj1);

console.log(wm);
// WeakMap {Array(3) => Array(3)}

3-2-3 检测是否包含某个元素

使用has()方法实现

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakMap
let wm = new WeakMap();

wm.set(obj1, obj1).set(like, like);

wm.delete(obj1);

console.log(wm.has(obj1), wm.has(like));
// false   true

3-2-4 获取某个元素

使用get()方法获取对应的元素

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakMap
let wm = new WeakMap();

wm.set(obj1, obj1).set(like, like);

console.log(wm.get(obj1), wm.get(like));
// {uname: 'Tom', age: 12} (3) ['football', 'baskball', 'pingpong']

3-3 弱键

weakset中的weak意思是弱弱的引用。表示使用WeakSet存储的数据都是弱弱的引用着。不会阻止垃圾回收机制的回收

let newWm = new WeakMap();

newWm.set({id: 12});

向弱类型集合中添加一个新的对象,且添加后代码内没有返现该对象的引用,那么这个集合内的该对象将会被垃圾回收机制回收

若是以下这种情况

let m = new WeakMap();

let o = {
	uname = 'TOM'
}

m.set(o);

这里向集合内添加一个o对象,且代码内保存着o变量对对象的引用,那么垃圾回收机制便不会立即回收这个对象。若是将o变量重新赋值,那么原来保存的对象变回被回收。

3-4 不可迭代键

因为WeakMap中的值任何时候都有可能销毁,所以迭代它就显得没有意义,同样也不需要向Map中的Clear()方法


4、WeakSet

ES6中新增的’弱集合’,WeakSet是Set的兄弟类型,api也是set的子集。JavaScript垃圾回收机制对待这种弱类型set有特殊的处理方式。

4-1 创建WeakSet

和set类型创建方式一致

let ws = new WeakSet();

注意:传入WeakSet集合的元素必须是Object或者继承自Object类型

4-2 WeakSet Api

4-2-1 添加元素

通过add()方法实现

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakSet
let ws = new WeakSet();

ws.add(obj1).add(like);

console.log(ws);
// WeakSet {{uname: 'Tom', age: 12}, ['football', 'baskball', 'pingpong']}

4-2-2 删除某个元素

使用delete()方法实现删除某一个元素

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakSet
let ws = new WeakSet();

ws.add(obj1).add(like);

ws.delete(like);

console.log(ws);
// {uname: 'Tom', age: 12}

4-2-3 检测是否包含某个元素

使用has()方法实现

let obj1 = {
	uname: 'Tom',
	age: 12
},
like = ['football', 'baskball', 'pingpong'];

// 创建WeakSet
let ws = new WeakSet();

ws.add(obj1).add(like);

ws.delete(like);

console.log(ws);
// {uname: 'Tom', age: 12}

console.log(ws.has(like), ws.has(obj1));
// false  true

4-3 弱值引用

weakset中的weak意思是弱弱的引用。表示使用WeakSet存储的数据都是弱弱的引用着。不会阻止垃圾回收机制的回收

let newWs = new WeakSet();

newWs.add({id: 12});

向弱类型集合中添加一个新的对象,且添加后代码内没有返现该对象的引用,那么这个集合内的该对象将会被垃圾回收机制回收

若是以下这种情况

let s = new WeakSet();

let o = {
	uname = 'TOM'
}

s.add(o);

这里向集合内添加一个o对象,且代码内保存着o变量对对象的引用,那么垃圾回收机制便不会立即回收这个对象。若是将o变量重新赋值,那么原来保存的对象变回被回收。

4-4 不可迭代值

因为WeakSet中的值任何时候都有可能销毁,所以迭代它就显得没有意义,同样也不需要向Set中的Clear()方法

4-5 WeakSet 避免内存泄漏

/*
* WeakSet 避免内存泄漏 -- 被垃圾回收
* */


let obj1 = {
    id: 10
}, obj2 = {
    bool: true
}

let set = new Set([obj1, obj2]);

console.log(set);
// Set(2) {{id: 10}, {bool: true}}

obj2 = null;

setTimeout(() => {
    console.log(set);
    // Set(2) {{id: 10}, {bool: true}}
}, 3000)

// -----------------------------------------------------------

let obj3 = {
    id: 10
}, obj4 = {
    bool: true
}

let wSet = new WeakSet([obj3, obj4]);

console.log(wSet);
// WeakSet {{id: 10}, {bool: true}}

obj4 = null;


setTimeout(() => {
    console.log(wSet);
    // WeakSet {{id: 10}}
}, 3000);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值