ECMAScript6(11):Set 与 Map

WeakSet

WeakSet 和 Set类似,但是具有以下区别:

  • WeakSet 的元素只能是对象,不能是别的类型

  • WeakSet 的元素无法被引用,其元素不具有别的引用时,GC 会立刻释放对象的内存资源,因此 WeakSet 不能被遍历。

定义WeakSet和定义其他数据结构一样,其构造函数接受一个数组,集合或类数组对象初始化:

var set1 = new WeakSet();

var set2 = new WeakSet([[1,2],[3,3],[4,4,5]]);

console.log(set1); //WeakSet(0) {}

console.log(set2); //WeakSet {(2) [1, 2], (2) [3, 3], (3) [4, 4, 5]}

WeakSet 没有 size 属性,有如下3个方法:

  • add()方法: 相当于数组的push()方法,但只能接受一个参数

  • delete()方法: 删除集合中的一个值

  • has()方法: 判断数组的中是否含有某个值

WeakSet 不能遍历,它的作用是临时存储DOM节点,这样不必担心内存泄漏:

//例

const foos = new WeakSet();

class Foo{

constructor(){

foos.add(this);

}

method(){

if(!foos.has(this)){

throw new TypeError("foo.prototype.method" is only called by object of Foo);

}

console.log("Foo.prototype.method" has been called);

}

}

var obj = new Foo();

obj.method(); //Foo.prototype.method" has been called

obj.method.call({}); //typeError: “foo.prototype.method” is only called by object of Foo

Map

js 中的对象是键值对的集合,但是键只能是字符串其实并不方便。Map结构本质和对象一样,只是键名可以使用各种类型的值。如果这么理解,那么Map就是一种值-值对而不是键-值对,这一点类似hash结构:

var o = {name: “Bob”};

var map = new Map();

map.set(o, “hello”);

console.log(map.get(o)); //“hello”

构造 Map 结构的构造函数接受数组,对象等类型作为构造函数的参数:

var map = new Map([[“name”,“Bob”], [“age”, 12]]);

map.get(“name”); //“Bob”

map.get(“age”); //12

map具有如下属性和方法:

  • size 属性: 返回 map 中元素的数量,类似数组的 length

  • set(key, value)方法: 向map中添加值-值对

  • get(key)方法: 读取map中的值

  • delete(key, value)方法: 删除map中的值-值对

  • has(key)方法: 判断某个键名是否存在

  • clear()方法: 清空当前 map 中所以数据

  • keys()方法: 返回键名的遍历器,和数组keys()方法类似,用于 for…of 循环

  • values()方法: 返回值的遍历器,和数组values()方法类似,用于 for…of 循环

  • entires()方法: 返回值-值对的遍历器,和数组entires()方法类似,用于 for…of 循环

  • forEach()方法: 使用回调函数遍历集合成员,和数组forEach()方法类似

var o = {name: “Bob”};

var map = new Map();

map.set(o, “hello”);

console.log(map.get(o)); //“hello”

map.set(o, “world”); //重复定义,覆盖之前的定义

console.log(map.get(o)); //“world”

console.log(map.get({name: “Bob”})); //undefined, 不同的对象引用不认为是同一个对象

map.delete(o); //删除对象属性 o

console.log(map.get(o)); //undefined

从上方的例子不难发现,不同的对象属性对于 map 来说就是不同的,不管内部的内容是否一致。这和对象的 === 比较是一样的道理,带来的好处是我们不用担心和会 map 原有属性重名,而直接向 map 添加对象属性即可。

注意 undefined,NaN和 null 也可以作为 map 的键名

var map = new Map();

map.set(undefined, 1);

map.set(null, 2);

map.set(NaN, 3);

console.log(map.get(undefined)); //1

console.log(map.get(null)); //2

console.log(map.get(NaN)); //3

但使用过程中请注意以下几点:

  • 存入 map 的数据不会进行类型转换,即’5’和 5 是不一样的, {} 和 {}也是不一样的。

  • 内部采用严格相等比较元素,但-0等于+0,NaN也等于NaN。

map 的默认遍历器是 entries()

Map.prototype[Symbol.iterator] === Map.prototype.entries; //true

另外这里需要格外强调的是:

  • Set中的 has 方法是判断键值是否存在的,如 Set.prototype.has(value), WeakSet.prototype.has(value)

  • Map中的 has 方法是判断键名是否存在的,如 Map.prototype.has(key), WeakMap.prototype.has(key), Reflect.has(target, propertyKey)

Map解构转换技巧:

  • Map 转 Array

var map = new Map([[1,‘one’], [2, ‘two’], [3, ‘three’]]);

var keyArr = […map.keys()]; //[1,2,3]

var valueArr = […map.values()]; //[‘one’,‘two’,‘three’]

var entriesArr = […map.entries()]; //[[1,‘one’], [2, ‘two’], [3, ‘three’]]

var arr = […map]; //[[1,‘one’], [2, ‘two’], [3, ‘three’]]

  • Map 转 Object(为防止不必要的错误,直接丢弃不是字符串为键的属性)

function map2arr(map){

var o = {};

for(let [key, value] of map.entries()){

if(typeof key === ‘string’){

o[key] = value;

}

}

return o;

}

var map = new Map([[1,‘one’], [2, ‘two’], [‘three’, 3], [‘four’, 4]]);

map2arr(map); //Object {three: 3, four: 4}

  • Map 转 JSON

var map = new Map([[1,‘one’], [2, ‘two’], [‘three’, 3], [‘four’, 4]]);

JSON.stringify([…map]); //“[[1,“one”],[2,“two”],[“three”,3],[“four”,4]]”

WeakMap

WeakMap 和 map 类似,不过它只接受对象作为键名,null除外。试想,如果对象 o 是一个 map的属性,如果该对象被释放了,那这个 map 属性会导致内存溢出。解决这个问题就是使用 WeakMap:

var o = {name: “Bob”};

var map = new WeakMap();

map.set(o, 12);

console.log(map.get(o)); //12

o = null;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
1Kr-1715348394544)]

[外链图片转存中…(img-ahr1Arbr-1715348394544)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 22
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值