javascript中Set、Map、WeakSet、WeakMap区别

前言

在学习vue官方源码解析的过程中,看到了有关这一块的解析,所以跟着学习并且记录一下

Set

之前我对Set的了解还是仅仅停留在数组去重,但是我并没有在项目中用过,深入学习后,发现有时候用这个特性还挺方便的。
介绍Set之前我们先来介绍一下集合,集合是由一群无序的、不重复的元素组成的集合。
Set对象是一个由任意唯一值组成的的集合,这个唯一值可以是基本类型,也可以是引用类型,并且Set是可迭代的。

Set的使用

const set = new Set([1, 2, 3, 4, 5, 6, 5, 6]);
console.log(set);

运行代码可知Set()方法最终生成的是一个去重过后的类数组结构对象。

属性

返回类数组的元素数量

const set = new Set([1, 2, 3, 4, 5, 6, 5, 6]);
console.log(set.size); // size: 6

方法

  • add(value): 向集合中添加一个新的项
let set = new Set();
set.add(1);
console.log(set); // set: { 1 }
  • delete(value): 从集合中删除一个值
let set = new Set();
set.add(1);
set.add(2);
set.delete(1);
console.log(set); // set: { 2 }
  • has(value): 如果值在集合中存在,返回ture, 否则返回false
let set = new Set();
set.add(1);
console.log(set.has(1)); // true
console.log(set.has(2)); // false
  • clear(): 移除集合中的所有项
let set = new Set();
set.add(1);
set.add(2);
set.clear();
console.log(set.clear()) // undefined
console.log(set) // {size:0}

遍历方法

因为Set方法返回的数据结构是类数组,所以我们要使用Array,form()去将其转化为数组,也可以用ES6的结构将其转化为数组
因为Set是值的集合,它没有键,只有值,所以遍历键和值是的结果是一样的。

keys(): 返回键名的遍历器

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

values(): 返回键值的遍历器

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

entries(): 返回键值对的遍历器(解构类数组)

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

forEach(): 使用回调函数遍历每个成员

let set = new Set([1, 2, 3, 4]);
set.forEach((item: number) => {
    console.log(item); // 轮流输出1,2,3,4
});

小结

当我们的业务需求中有数组去重时可以用,代码量少

也可以用于去交集并集差集时可以用

// 数组去重
let arr = [1, 2, 3, 4, 5, 5];
let arrSet = [... new Set(arr)]; // [1,2,3,4]

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 并集
let union = [...new Set([...a, ...b])]; // [1,2,3,4]

// 交集
let intersect = [...new Set([...a].filter(x => b.has(x)))]; // [2,3]

// 差集
let difference = Array.from(new Set([...a].filter(x => !b.has(x)))); // [1]

JS垃圾回收机制

介绍WeakSetWeakMap时得先简单的介绍一下垃圾回收机制

什么是垃圾回收机制

搞清楚什么是垃圾回收机制,首先要知道什么是垃圾,所谓的垃圾指的是不再被使用的变量和引用的对象,也有可能是对象直接相互访问,导致的死循环。那么垃圾回收机制就是不停的在寻找这些不再被使用的和不再被引用的变量,将他们清除并且释放内存。

标记清除法

现在大多数浏览器使用的都是标记清除法,当变量在运行环境中被声明时给它添加一个标记,当变量离开运行环境时清除内存并清除标记

引用计数法

当我们在创建对象时,给对象的引用计数加一,对象引用完计数减一,最终当引用计数为0时,可被垃圾回收机制回收。

WeakSet

WeakSet是对象的集合,它的成员只能是对象,并且都是弱引用的对象,如何理解弱引用,就是当对象不再被引用时,对象会被垃圾回收机制回收,所以没法确认它的成员数量,所以WeakSet它是不可迭代的,无法使用forEach等方法去遍历。

WeakSet方法

add(value): 向集合中添加一个新的项

const Weakset = new WeakSet();

const a = {};
const b = {};

Weakset.add(a);
Weakset.add(b);
console.log(Weakset);

delete(value): 从集合中删除一个值

const Weakset = new WeakSet();

const a = {};
const b = {};

Weakset.add(a);
Weakset.add(b);
Weakset.delete(b);
console.log(Weakset);

has(value) 如果值在集合中存在,返回ture, 否则返回false

const a = {};
const b = {};

Weakset.add(a);
Weakset.add(b);
Weakset.delete(b);
console.log(Weakset.has(a)); // true
console.log(Weakset.has(b)); // false

Map

记得第一次接触Map还是在做算法题的时候,当时第一题用双重for循环的话,时间复杂度为O(n^2),但是用map来处理就变成了O(n),至今印象深刻。Map是由键和值组成的集合,就相当于将key也就是指针存在了栈内存中,通过指针去寻找它的值。并且Map是可迭代的集合,每次迭代后都会返回一个[key,value]的数组。

属性

size 返回集合元素的数量

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log(map.size); // 2

方法

set(key, value): 往Map中设置新的值

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log(map);

get(key): 通过key去获取它的值,如果拿不到就返回与undefined

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log(map.get('a')); // b
console.log(map.get('c')); // undefined

has(key): 判断当前键是否在当前集合中,返回一个布尔值,存在返回true,不存在则返回false

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log(map.has('a')); // true
console.log(map.has('c')); // false

delete(key): 删除集合中的某个元素,通过key去查找,删除后返回一个布尔值,删除成功返回true,否则返回false

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log(map.delete('a'));
console.log(map);

5. clear(): 删除集合中的所有元素,没有返回值

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log(map.clear()); // undefined
console.log(map); // {size: 0}

遍历方法

keys():返回的是一个迭代后的对象,其中包含着Map对象所有的键。

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log([...map.keys()]); // ['xiao', 'a']

values():返回的是一个迭代后的对象,其中包含Map对象中所有的值。

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log([...map.values()]); // ['chen', 'b']

entries():返回的是一个迭代后的对象,其中包含Map对象中所有的键值对。

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');
console.log([...map.entries()]);

forEach():遍历Map对象的所有成员

let map = new Map();
map.set('xiao', 'chen');
map.set('a', 'b');

map.forEach((value, key) => {
    console.log(key, value);
});
// xiao chen
// a b

WeakMap

WeakMap和Map一样是键值的集合,但是它的键必须是对象,并且它的键也是弱引用,所有它也有可能被垃圾回收机制所回收且是不可迭代的

以上就是javascript中Set、Map、WeakSet、WeakMap区别的详细内容,更多关于javascript中Set、Map、WeakSet、WeakMap区别的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详谈js遍历集合(Array,Map,Set)

    Array可以使用下标,Map和Set不能使用下标,ES6引入了iterable类型,Array,Map,Set都属于iterable类型,它们可以使用for...of循环来遍历: var a = ['A', 'B', 'C']; var s = new Set(['A', 'B', 'C']); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); for (var x of a) { // 遍历Array alert(x); } for (var

  • JavaScript之Map和Set_动力节点Java学院整理

    JavaScript的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对. 但是JavaScript的对象有个小问题,就是键必须是字符串.但实际上Number或者其他数据类型作为键也是非常合理的. 为了解决这个问题,最新的ES6规范引入了新的数据类型Map.要测试你的浏览器是否支持ES6规范,请执行以下代码,如果浏览器报ReferenceError错误,那么你需要换一个支持ES6的浏览器: 'use strict'; var m = new Map();

  • javascript ES6中set集合、map集合使用方法详解与源码实例

    set与map理解 ES6中新增,set集合和map集合就是一种数据的存储结构(在ES6之前数据存储结构只有array,object),不同的场景使用不同的集合去存储数据 set集合 Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用. set集合语法: //创建一个set集合,传参为一个可迭代的对象 const s1 = new Set(iterable); API 名称 类型 简介 Set.add() 原型方法 添加数据 Set.has() 原型方法 判断是否存在一个数据 S

  • js中Map和Set的用法及区别实例详解

    目录 首先了解一下 Map 再来了解一下 Set 总结Map和Set的区别 结语: 首先了解一下 Map Map 是一组键值对的结构,和 JSON 对象类似. (1) Map数据结构如下 这里我们可以看到的是Map的数据结构是一个键值对的结构 (2) key 不仅可以是字符串还可以是对象 var obj ={name:"小如",age:9} let map = new Map() map.set(obj,"111") 打印结果如下 (3) Map常用语法如下 //初

  • JavaScript Set与Map数据结构详细分析

    目录 Set 基本使用 遍历操作 Map 基本使用 Set ES6提供了新的数据结构 Set(集合).它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用 [扩展运算符] 和 [for...of] 进行遍历. 基本使用 添加新的元素 Set函数可以接受一个数组(或者具有iterable接口的其他数据结构)作为参数,用来初始化. <script> // 声明一个 set let s = new Set([1,2,2,3,4,4,5]) //Set方法会自动去重 //

  • 详解 Map 和 WeakMap 区别以及使用场景

    一.为什么是 Map ? 1. 传统对象结构 Map本质上是一个键值对的集合.和传统对象结构相比,传统的对象只能用「字符串作为键名」,这就在使用上造成了很大的限制了.这也是新增 Map 的原因之一. const data = {}; // element 为节点对象 const element = document.querySelector(".node"); console.log(element); // 输出 div.node 对象 // 将对象转化成字符串输出 [object

  • JavaScript中实现Map的示例代码

    不废话了,直接贴代码了. 代码一: var map=new Map(); map.put("a","A");map.put("b","B");map.put("c","C"); map.get("a"); //返回:A map.entrySet() // 返回Entity[{key,value},{key,value}] map.containsKey('kevin'

  • JavaScript中object和Object的区别(详解)

    JavaScript中object和Object有什么区别,为什么用typeof检测对象,返回object,而用instanceof 必须要接Object呢 这个问题和我之前遇到的问题非常相似,我认为这里有两个问题需要解决,一个是运算符new的作用机制,一个是function关键字和Funtion内置对象之间的区别.看了一些前辈的博客和标准,这里帮提问者总结一下. 1.new new运算符的作用是创建一个对象实例.这个对象可以是用户自定义的,也可以是带构造函数的一些系统自带的对象.如果 new

  • javascript中局部变量和全局变量的区别详解

    javascript有两种变量:局部变量和全局变量.当然,我们这篇文章是帮助大家真正的区别这两种变量. 首先,局部变量是指只能在本变量声明的函数内部调用.全局变量时整个代码中都可以调用的变量.当然,单单从字面上理解肯定是不清楚的,下面我详细的介绍下: 大家都知道,变量是需要用var关键字声明的.但是javascript中也可以隐式的使用变量,就是不用声明,直接使用.而且,千万注意,javascript把隐式声明的变量总是当成全局变量来使用的. 例如: 复制代码 代码如下: function my

  • JavaScript中undefined和null的区别

     JavaScript中undefined和null的区别 JavaScript两个表示"无"的值:undefined和null.我在平时只是null用的多一点,undefined只是在报错中经常遇到.下面针对这两个数据类型的异同做一下详细的比较. 1.undefined和null在if语句中,都会被自动转为false,相等运算符直接报告两者相等. !null==!undefined==true 2.null表示"没有对象",即该处不应该有值.典型用法是: (1)

  • JavaScript中click和onclick本质区别与用法分析

    本文实例讲述了JavaScript中click和onclick本质区别与用法.分享给大家供大家参考,具体如下: 原生javascript的click在w3c里边的阐述是DOM button对象,也是html DOM click() 方法,可模拟在按钮上的一次鼠标单击. button 对象代表 HTML 文档中的一个按钮.button元素没有默认的行为,但是必须有一个 onclick 事件句柄以便使用. 语法:buttonObject.click() <html> <head> &l

  • javascript中call()、apply()的区别

    call().apply()的区别: 相同点: 1.call()和apply()都可以用来间接调用函数,都可以显式调用所需的this.即,任何函数可以作为任何对象的方法来调用. 2.两个方法都可以指定调用实参. 区别: call()和apply()的基本区别:在于将参数传递给函数. call():使用其自有的实参列表作为函数的参数: apply():要求以数组的形式传入参数. function track(o,m){ var original =o[m]; o[m] =function( ){

  • JavaScript中callee和caller的区别与用法实例分析

    本文实例讲述了JavaScript中callee和caller的区别与用法.分享给大家供大家参考,具体如下: 1.callee 在函数的内部,有两个特殊的对象:arguments和this.其中arguments是一个类似数组的对象,包含着传入函数的所有参数. 虽然arguments的主要用途是保存函数参数,但这个对象有一个属性--callee,该属性是一个指针,指向拥有这个arguments对象的函数 所以callee的作用就是来指向当前对象 看一个阶层函数的例子就会明白他的用途了: /* *

  • JavaScript中toLocaleString()和toString()的区别实例分析

    本文实例讲述了JavaScript中toLocaleString()和toString()的区别.分享给大家供大家参考,具体如下: <javascript高级程序设计>解释: "toLocaleString()返回对象的字符串表示,该字符串与执行环境的地区对应:toString()返回对象的字符串表示:" 感觉还是不太好理解......来看几个实例: 字符串: var a = 6666; a.toLocaleString(); //"6,666" a.t

  • javascript中call,apply,bind的区别详解

    在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢. 在说区别之前还是先总结一下三者的相似之处: 1.都是用来改变函数的this对象的指向的. 2.第一个参数都是this要指向的对象. 3.都可以利用后续参数传参. 那么他们的区别在哪里的,先看一个例子. var xw = { name : "小王", gender : "男", age : 24, say : function() { alert(this.name + " ,

随机推荐