[ES6] Map & Set
- Map
- Map 与 Object 区别
- Map 的初始化
- 键值是对象与函数的情况
- 键值是 NaN
- 方法的使用
- Map 的迭代
- Map 对象操作
- Map 与数组的转化
- Map 的克隆
- Map 的合并
- Set 对象
- Set 中的特殊值
- Set 的初始化
- 类型转换
- Array 与 Set 互相转换
- String 转 Set
- Set 方法
- Set 迭代
- Set 对象作用
- 数组去重
- Set 的合并-并集
- 交集
- 差集
Map
Map 与 Object 区别
Map 是用于保存键值对,似乎与 Object 非常类似
- 键值
Object 的键只能是字符串或者 Symbols(ES6 新增基础类型),但 Map 的键可以是任意值–包括对象、函数等 - 键值顺序
Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是 - 键值个数
Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动或其它自定义方法计算
并且 Object 都有原型,原型链上的键名(保留键)有可能和你在对象上的设置的键名产生冲突。
Map 的初始化
Map 的设置与应用也可查看Typescript 的 Map 对象,这部分简单介绍了键是字符串的 Map 的用法
//方法1
let myMap = new Map();
// 设置 Map 对象
myMap.set("key1", value1);
myMap.set("key2", value2);
myMap.set("key3", value3);
//方法2
let myMap = new Map([
["key1", "value1"],
["key2", "value2"]
]);
键值是对象与函数的情况
用变量表示对象与函数,应用 Map 的情况与字符串是一样的,但是有一些特殊情况需要注意:
let myMap = new Map();
let keyObj = {};
myMap.set(keyObj, "和键 keyObj 关联的值");
myMap.get(keyObj); // "和键 keyObj 关联的值"
myMap.get({}); // undefined, 因为 keyObj !== {}
函数也类似,所以复杂类型的键值并不是形式看着一样就是同一个值,必须是指针指向的是同一个地址的键值才能获取到对应值
键值是 NaN
let myMap = new Map();
myMap.set(NaN, "Key is NaN");
myMap.get(NaN); // "Key is NaN"
let otherNaN = Number("foo"); //Number(undefined)
myMap.get(otherNaN); // "Key is NaN"
我们知道 NAN 是和任意值都不相等的,甚至它自己
,但是在上述的测试中发现 Map 中,Map 认为 NaN 作为键值的时候被认为是相等
并且当 Number()的参数是 string 类型与 undefined 的时候,myMap.get(otherNaN)
的结果也和 NaN 是相同的
其它的情况,包括myMap.get(undefined)
,myMap.get(null)
直接获取,设置otherNaN
其它可能与 NaN 相等的情况均是 undefined
let otherNaN = Number(true); //Number(false)
myMap.get(undefined); //undefined
myMap.get(null); //undefined
myMap.get(otherNaN); //undefined
## Map 方法
Map 方法 | 描述 |
---|---|
map.clear() | 移除 Map 对象的所有键/值对 |
map.set() | 设置键值对,返回 Map 对象 |
map.get() | 返回键对应的值,如果不存在,则返回 undefined |
map.has() | 返回布尔值,用于判断 Map 中是否包含键对应的值 |
map.delete() | 删除键对应元素,成功返回 true,失败或不存在返回 false |
map.size | 返回 Map 对象键/值对的数量 |
map.keys() | 返回 Iterator 对象, 包含了 Map 对象中每个元素的键 |
map.values() | 返回 Iterator 对象,包含了 Map 对象中每个元素的值 |
map.entries() | 返回键值对数组迭代对象. map.entries().next().value 可返回每个值 |
方法的使用
let nameSiteMapping = new Map();
// 设置 Map 对象
nameSiteMapping.set("Google", 1);
nameSiteMapping.set("Runoob", 2);
nameSiteMapping.set("Taobao", 3);
// 获取键对应的值
console.log(nameSiteMapping.get("Runoob")); // 2
// 判断 Map 中是否包含键对应的值
console.log(nameSiteMapping.has("Taobao")); // true
console.log(nameSiteMapping.has("Zhihu")); // false
// 返回 Map 对象键/值对的数量
console.log(nameSiteMapping.size); // 3
// 删除 Runoob
console.log(nameSiteMapping.delete("Runoob")); // true
console.log(nameSiteMapping);
// 移除 Map 对象的所有键/值对
nameSiteMapping.clear(); // 清除 Map
console.log(nameSiteMapping);
Map 的迭代
Map 对象中的元素是按顺序插入的,迭代 Map 对象也是按顺序迭代,每一次迭代返回 [key, value] 数组
let nameSiteMapping = new Map();
nameSiteMapping.set("Google", 1);
nameSiteMapping.set("Runoob", 2);
nameSiteMapping.set("Taobao", 3);
// 迭代 Map 中的 key
for (let key of nameSiteMapping.keys()) {
console.log(key);
}
// 迭代 Map 中的 value
for (let value of nameSiteMapping.values()) {
console.log(value);
}
// 迭代 Map 中的 key => value
for (let entry of nameSiteMapping.entries()) {
console.log(entry[0], entry[1]);
}
// 使用对象解析
for (let [key, value] of nameSiteMapping) {
console.log(key, value);
}
nameSiteMapping.forEach(function (value, key) {
console.log(key + " = " + value);
}, nameSiteMapping);
forEach 方法的第二个参数,表示绑定处理函数内部的 this 对象,如果省略则表示是调用对象本身,上述可省略第二个参数
Map 对象操作
Map 与数组的转化
let array = [
["key1", "value1"],
["key2", "value2"]
];
// Map 构造函数可以将 二维 键值对数组转换成Map 对象
let myMap = new Map(array);
// 使用 Array.from 函数可以将Map 对象转换成二维键值对数组
let outArray = Array.from(myMap);
Map 的克隆
Map 的克隆是 Map 对象构造函数生成实例,迭代出新的对象
let myMap1 = new Map([
["key1", "value1"],
["key2", "value2"]
]);
let myMap2 = new Map(myMap1);
console.log(myMap1 === myMap2); // false
Map 的合并
REST 运算符合构建新的数组
合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的
let first = new Map([
[1, "one"],
[2, "two"],
[3, "three"]
]);
let second = new Map([
[1, "uno"],
[2, "dos"]
]);
// 对应值即 uno,dos,three
let merged = new Map([...first, ...second]);
Set 对象
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
Set 结构的键名就是键值
Set 中的特殊值
Set 对象存储的值总是唯一的
,所以需要判断两个值是否恒等,恒等则不能同时存在。有几个特殊值需要特殊对待:
- +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复;
- undefined 与 undefined 是恒等的,所以不重复;
- NaN 与 NaN 是不恒等的,但是在
Set 中只能存一个 NaN
,不重复。
Set 的初始化
let mySet = new Set(); //Set(0) {}
mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性
mySet.add("some text"); // Set(3) {1, 5, "some text"} 这里体现了类型的多样性
let o = { a: 1, b: 2 };
mySet.add(o); // Set(5) {1, 5, "some text", {…}}
mySet.add({ a: 1, b: 2 }); // Set(5) {1, 5, "some text", {…}, {…}}
// 这里体现了对象之间引用不同不恒等,即使值相同,内存地址并不相同
以上是先创建空集合,使用了 add 方法设置 Set 的值
new Set()通过直接传递参数初始化的方式 请查看下面的类型转换
类型转换
Array 与 Set 互相转换
let mySet = new Set(["value1", "value2", "value3"]); // Array 转 Set
console.log(mySet); //Set(3) { 'value1', 'value2', 'value3' }
let myArray = [...mySet]; // 用...操作符,将 Set 转 Array
String 转 Set
let mySet = new Set("hello"); // Set(4) {"h", "e", "l", "o"}
// 注:Set 中 toString 方法不能将 Set 转换成 String
Set 方法
Set 方法 | 描述 |
---|---|
set.clear() | 清空 set 实例,无返回值 |
set.add() | 添加 set 成员 |
set.has() | Set 是否包含成员,包含返回 true |
set.delete() | 删除成员,成功返回 true,其它返回 false |
set.size | 返回 Map 对象键/值对的数量 |
set.keys() | 返回键名的 Iterator 对象 |
set.values() | 返回键值的 Iterator 对象 |
set.entries() | 返回键值对迭代对象 |
set.forEach() | 回调函数遍历每个成员 |
Set 迭代
Set 结构的键名就是键值,因此两者相同
let set = new Set(["value1", "value2", "value3"]);
for (let item of set.keys()) {
console.log(item);
}
for (let item of set.values()) {
console.log(item);
}
for (let item of set.entries()) {
console.log(item);
}
set.forEach((value, key) => console.log(value));
//打印
//value1
//value2
//value3
Set 对象作用
数组去重
let mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]
利用 Set 值的唯一性
Set 的合并-并集
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 a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
let intersect = new Set([...a].filter((x) => b.has(x))); // {2, 3}
差集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
let difference = new Set([...a].filter((x) => !b.has(x))); // {1}