JS学习笔记(十四)Map、WeakMap、Set、WeakSet用法及总结【ES6新增】

JS学习笔记(十四)

本系列更多文章,可以查看专栏 JS学习笔记



一、Map【映射】

使用 new 关键字和 Map 构造函数,可以创建一个空映射;传入一个可迭代对象,需要包含键/值对数组,且会按照迭代顺序插入到新映射实例中。

1. 初始化映射

通过 size 属性可以获取 Map 对象的大小
注:键不可以重复,否则会按添加顺序靠后的覆盖前面的

// 使用嵌套数组初始化映射
const m1 = new Map([
	["k1", 100],
	["k2", 200],
 	["k1", 100]
]);
 console.log(m1); // Map(2) {'k1' => 100, 'k2' => 200}

// 使用自定义迭代器初始化映射
const m2 = new Map({
	[Symbol.iterator]: function* () {
		yield ["k1", 100];
		yield ["k2", 200];
		yield ["k1", 100];
	}
});
console.log(m2.size); // 2

2. 基本API

在映射中作为键和值的对象及其它“集合”类型,在自己的内容或属性被修改时仍然保持不变

  • (1)set(),初始化Map对象后,添加键/值对
  • (2)get(),获取Map对象中指定键的值,并返回该值
  • (3)has(),判断Map对象中是否包含指定的键,并返回布尔值
  • (4)delete(),删除Map对象中指定键/值对
  • (5)clear(),清空Map对象中所有键/值对

set()方法返回映射实例,可以把多个操作连缀起来,包括初始化声明

const m = new Map();
const objKey = {},
	objVal = {},
	arrKey = [],
	arrVal = [];

m.set(objKey, objVal);
m.set(arrKey, arrVal);
console.log(m.get(objKey)); // {}
console.log(m.get(arrKey)); // []

objKey.foo = "foo";
objVal.bar = "bar";
arrKey.push("foo");
arrVal.push("bar");
console.log(m.get(objKey)); // {bar: 'bar'}
console.log(m.get(arrKey)); // ['bar']

console.log(m.delete(objKey)); // true【删除成功】
console.log(m.has(objKey)); // false
console.log(objKey, objVal); // {foo: 'foo'} {bar: 'bar'}
m.clear();
console.log(m); // Map(0) {size: 0}

3. 相等比较算法

注:Map 内部使用 SameValueZero 进行比较操作,以下内容参考 《ES标准中的相等比较算法 SameValue和SameValueZero》

=====SameValueSameValueZero
NaN和NaNfalsefalsetruetrue
+0和-0truetruefalsetrue
0和+0truetruetruetrue
0和-0truetruefalsetrue
const m = new Map([
	[NaN, "NaN1"],
	[NaN, "NaN2"],
	[-0, "-0"],
	[0, "0"],
	[+0, "+0"]
]);
console.log(NaN == NaN, NaN === NaN, Object.is(NaN, NaN)); // false false true
console.log(+0 == -0, +0 === -0, Object.is(+0, -0)); // true true false
console.log(0 == +0, 0 === +0, Object.is(0, +0)); // true true true
console.log(0 == -0, 0 === -0, Object.is(0, -0)); // true true false
// Map中不允许两个相同的键
console.log(m); // Map(2) {NaN => 'NaN2', 0 => '+0'}

4. 顺序和迭代

映射实例会提供一个迭代器(iterator),能以插入顺序生成[key,value]形式的数组。可以通过 entries() 方法或者 symbol.iterator 属性取得这个迭代器。

entries() 或者 [Symbol.iterator]() :用于获取映射实例的迭代器
keys() :用于获取映射实例的键,并且返回可以迭代对象
values() :用于获取映射实例的值,并且返回可以迭代对象

const m = new Map([
	["key3", 16],
	["key5", 19],
	["key1", 28]
]);

// 获取映射实例的迭代器 - 方式1
for (let entry of m.entries()) {
	console.log(entry);
}

// 获取映射实例的迭代器 - 方式2
for (let iter of m[Symbol.iterator]()) {
	console.log(iter);
}

// 获取映射实例所有的键
console.log(m.keys()); // MapIterator {'key3', 'key5', 'key1'}
// 获取映射实例所有的值
console.log(m.values()); // MapIterator {16, 19, 28}

二、WeakMap【弱映射】

1. 初始化弱映射

注:弱映射中的键只能是 Object 或者继承自 Object 的类型;值的类型没有限制。

const key1 = { id: "key1" };
const key2 = { id: "key2" };
const wm = new WeakMap([
	[key1, "value1"],
	[key2, "value2"]
]);

console.log(wm);
vm.set("key3", "value3"); // Uncaught ReferenceError: vm is not defined

2. 基本API

区别于Map对象,没有 size 属性,也没有clear() 方法

  • (1)set(),初始化Map对象后,添加键/值对
  • (2)get(),获取Map对象中指定键的值,并返回该值
  • (3)has(),判断Map对象中是否包含指定的键,并返回布尔值
  • (4)delete(),删除Map对象中指定键/值对

3. 弱键

相比于 Map 对象会使用两个数组(一个存放键,一个存放值),原生的 WeakMap 持有的每个键对象的“弱引用”。

这意味着,在没有其它引用存在时,垃圾回收可以正常进行,其用于映射的键对象,只有被回收时才是有效的。
因此,弱映射对象是不可枚举的!!


三、Set【集合】

使用 new 关键字和 Set 构造函数,可以创建一个空集合;传入一个可迭代对象,需要包含插入到新集合实例中的元素

1. 初始化映射

通过 size 属性可以获取 Set 对象元素数量。

// 使用数组初始化集合
const s1 = new Set(["v1", "v2", "v3"]);
console.log(s1); // Set(3) {'v1', 'v2', 'v3'}

// 使用自定义迭代器初始化集合
const s2 = new Set({
	[Symbol.iterator]: function* () {
		yield "v1";
		yield "v2";
		yield "v3";
	}
});
console.log(s2.size); // 3

2. 基本API

Map 类似, Set 可以包含任何 JavaScript数据类型作为值;用作值的对象和其他“集合”类型在自己的内容或属性被修改时,也不会改变。

  • (1)add(),初始化Set对象后,增加值
  • (2)has(),判断Set对象中是否包含指定的元素,并返回布尔值
  • (3)delete(),删除Set对象中指定元素
  • (4)clear(),清空Set对象中所有元素

add()delete() 操作是幂等的(即执行多次,也相当于执行1次)

const s = new Set();
s.add("v1");
console.log(s.size); // 1
s.add("v1");
console.log(s.size); // 1

注:Set 内部同样使用 SameValueZero 进行比较操作

3. 顺序和迭代

Set 会维护值插入时的顺序,支持按顺序迭代。可以通过 values() 方法及别名方法 keys() 方法或者 symbol.iterator 属性取得这个迭代器。

values() 或者 [Symbol.iterator]() :用于获取集合实例的迭代器
keys() :是 values() 的别名方法
entries() :可以按照插入顺序产生包含两个元素的数组,这两个元素是集合中每个值的重复出现。

const s3 = new Set(["val1"]);
for (let v of s3.values()) {
	console.log(v); // val1
	v = "newVal1";
	console.log(v); // newVal1
	console.log(s3.has(v)); // false
	console.log(s3.has("val1")); // true
}

四、WeakSet【弱集合】

注:弱集合中的值只能是 Object 或者继承自 Object 的类型;值的类型没有限制。

1. 基本API

区别于Set对象,没有 size 属性,也没有clear() 方法

  • (1)add(),初始化WeakSet对象后,增加值
  • (2)has(),判断WeakSet对象中是否包含指定的元素,并返回布尔值
  • (3)delete(),删除WeakSet对象中指定元素

2. 用途

可以用于给对象打标签,便于当任何元素从DOM树中被删除,而立即释放其内存。
在这里插入图片描述


五、总结

1. Object、Map、WeakMap、Set、WeakSet对比与总结

ObjectMapWeakMapSetWeakSet
键类型只能 使用 数值、字符串或者symbol类型可以 使用 任何JavaScript类型只能 使用 Object类型或者继承自Object类型
值类型无限制无限制无限制可以 使用 任何JavaScript类型只能 使用 Object类型或者继承自Object类型
size属性
迭代可迭代可迭代不可迭代可迭代不可迭代
基本API自行查询set()、has()、get()、delete()、clear()set()、has()、get()、delete()add()、has()、delete()、clear()add()、has()、delete()
查找速度自行查询set()、has()、get()、delete()、clear()set()、has()、get()、delete()add()、has()、delete()、clear()add()、has()、delete()

2. Object与Map的区别

  1. Object只能使用数值、字符串或Symbol作为键;Map可以使用任何JS数据类型作为键。
  2. Map与Object类似,映射的值是没有限制的。
  3. Map的键是有序的,Object的键是无序的
  4. Map的查找速度 > Object的查找速度

3. Map与Set的区别

  1. 两种数据类型查找速度均很快
  2. Map类型利用二维数组进行初始化,Set类型利用一维数组进行初始化
  3. Map数据类型称为字典,Set数据类型称为集合
  4. Map的键唯一,值不唯一;Set的值就是键,键是唯一的
  5. Map的键值对有序,Set的值无序
  6. Map的键不可以修改,值可以修改;Set不可以通过迭代器来修改值
  7. Map以键值对形式存在,Set的value就是其key

结尾

部分内容参考《ECMAScript 6 入门》《JavaScript权威指南》《JavaScript高级程序设计》,如有错误,欢迎评论区指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要大口炫榴莲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值