Map and Set(映射和集合)

JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object)。
在ES6,引入了MapSet

Map

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值)都可以作为键或值。(请查看mdn

从定义上来看,Map 是一个带键的数据项的集合,就像一个 Object 一样。

Map的方法和属性

  • new Map() —— 创建 map。
  • map.set(key, value) —— 根据键存储值。
  • map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined。
  • map.has(key) —— 如果 key 存在则返回 true,否则返回 false。
  • map.delete(key) —— 删除指定键的值。
  • map.clear() —— 清空 map。
  • map.size —— 返回当前元素个数。
let map = new Map();

map.set("string", "str1");   // 字符串键
map.set(1, "Number");     // 数字键
map.set(true, "Boolean"); // 布尔值键
map.set({"键名": "键值"}, "Object");  // 使用对象作为键
map.set(function() {}, "Function");  // 使用方法作为键

// 还记得普通的 Object 吗? 它会将键转化为字符串
// Map 则会保留键的类型,所以下面这两个结果不同:
console.log( map.get(1)); // 'num1'
console.log( map.get('1') ); // 'str1'
console.log( map.size ); // 5

MapObject 都允许按键存取一个值、删除键、检测一个键是否绑定了值。

Map和Object的区别

  1. Object 只能接收两种类型的键名:StringSymbol
    Map 能够接受任意类型的键名(包括函数、对象或任何原始值)。
let map =new Map();
// 链式调用
map.set(1, "Number").set(true, "Boolean").set({"键名": "键值"}, "Object")

map.set(function() {}, "Function")
console.log(map);

let obj = {
	1: "Number",
	true: "Boolean",
	[{"键名": "键值"}]: "Object",
	[function() {}]: "Function"
}
console.log(obj)

在这里插入图片描述
在这里插入图片描述
虽然说Object 可以接受其他类型的键名,当时js都会隐式地将其转换为字符串

  1. Map是可迭代对象,具备iterator接口,可以直接迭代。
    Object 没有实现可迭代协议,是不能直接进行迭代的。
let map =new Map();
// 链式调用
map.set(1, "Number").set(true, "Boolean").set({"键名": "键值"}, "Object")

map.set(function() {}, "Function")
console.log(map);
for(let it of map) {
	console.log(it)
}
  1. Map可以通过map.size()直接获取当前元素个数。
    Object不能直接获取。一般是通过 Object.keys() 返回对象中每一项key的数组,来获取当前对象的元素个数。

Map 迭代

如果要在 map 里使用循环,可以使用以下三个方法:

  • map.keys() —— 遍历并返回一个包含所有键的可迭代对象。
  • map.values() —— 遍历并返回一个包含所有值的可迭代对象。
  • map.entries() —— 遍历并返回一个包含所有实体 [key, value] 的可迭代对象。
// Map初始化要用二维数组
let map = new Map([
  ["string", "str1"],
  ["1", "Number"],
  ['tomatoes', 350],
  ['onion',    50]
]);
// 遍历所有的键
for (let vegetable of map.keys()) {
  console.log(vegetable); // string, 1, tomatoes, onion
}

// 遍历所有的值
for (let amount of map.values()) {
  console.log(amount); // str1, Number, 500, 350, 50
}

// 遍历所有的实体 [key, value]
for (let entry of map) { // 与 recipeMap.entries() 相同
  console.log(entry); 
}

// 此外,Map还有内建的forEach方法
// 对每个键值对 (key, value) 运行 forEach 函数
map.forEach( (value, key, map) => {
  console.log(`${key}: ${value}`); 
});

注意:Map初始化要用二维数组!!

Object.entries:从对象Object创建 Map

Object.entries(obj)方法返回对象的键/值对数组,该数组格式就是 Map 所需的格式。

let obj = {
	name: "张三",
	age: 18
}

// Object.entries返回键/值对数组
let objEntries = Object.entries(obj); // [ ["name","张三"], ["age", 18] ]
console.log(objEntries)

let map = new Map(objEntries)
console.log(map)

在这里插入图片描述

Object.fromEntries:从 Map 创建 对象Object

Object.fromEntries 方法:给定一个具有 [key, value] 键值对的数组,它会根据给定数组创建一个对象。
简而言之,使用 Object.fromEntries把键/值对数组转成普通对象(plain object)。

let map = new Map([
	["name", "张三"],
	["age", 18],
])

let obj = Object.fromEntries(map)
console.log(obj)  // {name: '张三', age: 18}

let obj1 = Object.fromEntries(map.entries()); 
console.log(obj1)  // {name: '张三', age: 18}

上面两句代码的作用是一样的,因为 Object.fromEntries 期望得到一个可迭代对象作为参数,而不一定是数组。
Map 的标准迭代会返回跟 map.entries() 一样的键/值对。
因此,我们可以获得一个普通对象(plain object),其键/值对与 map 相同。

Set

Set 对象允许你存储任何类型(无论是原始值还是对象引用)的唯一值。(请查看mdn

Set 对象是值的合集(collection)。集合(set)中的元素只会出现一次,即集合中的元素是唯一的。
Set 没有键!!

Set是一种特殊的对象,长得像数组,但是用的是花括号!!

let set = new Set(["a", "b", "c"]);
console.log(set); // Set(3) {'a', 'b', 'c'}
console.log(typeof set); // object
console.log(set instanceof Set); // true

Set的方法

  • new Set(iterable) —— 创建一个 set,如果提供了一个 iterable 对象(通常是数组),将会从数组里面复制值到 set 中。
  • set.add(value) —— 添加一个值,返回 set 本身
  • set.delete(value) —— 删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 false。
  • set.has(value) —— 如果 value 在 set 中,返回 true,否则返回 false。
  • set.clear() —— 清空 set。
  • set.size —— 返回元素个数。

因为Set 里面的每一个值只出现一次,所以 重复使用同一个值调用 set.add(value) 并不会发生什么改变。
Set 内部对唯一性检查进行了更好的优化。

let set = new Set();

let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };

// 重复使用一个值调用set.add
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);

// set 只保留不重复的值
console.log(set)
console.log( set.size ); // 3

for (let it of set) {
  console.lot(it.name); // John(然后 Pete 和 Mary)
}

Set 迭代(iteration)

let set = new Set(["oranges", "apples", "bananas"]);

for (let value of set) console.log(value);

// 与 forEach 相同:
set.forEach((value, valueAgain, set) => {
  console.log(value);
});

注意:使用forEach,同一个值在参数里出现了2次。
forEach 的回调函数有三个参数:一个 value,然后是 同一个值 valueAgain,最后是目标对象。
forEach 的回调函数有三个参数,是为了与 Map 兼容。

Map 中用于迭代的方法在 Set 中也同样支持:

  • set.keys() —— 遍历并返回一个包含所有键的可迭代对象。
  • set.values() —— 遍历并返回一个包含所有值的可迭代对象。

因为Set没有键(key),所以keys()values()返回结果相同。这是为了兼容Map

let set = new Set(["oranges", "apples", "bananas"]);
console.log(set.keys());  // SetIterator {'oranges', 'apples', 'bananas'}
console.log(set.values()); // SetIterator {'oranges', 'apples', 'bananas'}
  • set.entries() —— 遍历并返回一个包含所有的实体 [value, value] 的可迭代对象。

Set没有键(key),entries()方法返回的是[value, value]值值对,而不是[key, value]键值对,这是为了兼容Map

let set = new Set(["oranges", "apples", "bananas"]);
console.log(set.entries());  // SetIterator {'oranges' => 'oranges', 'apples' => 'apples', 'bananas' => 'bananas'}

for(let it of set.entries()) {
	console.log(it) // ['oranges', 'oranges'] and so on
}

将Set转为数组

使用Array.from或者扩展运算符(...)可以将Set转为数组。

let set = new Set(["a", "b", "c"]);
console.log(set); // Set(3) {'a', 'b', 'c'}

let arr = Array.from(set);  // ["a", "b", "c"]
let arr1 = [...set];  // ["a", "b", "c"]

将数组转为Set

// 方法1
let arr = ["a", "b", "c"]
let set = new Set(["a", "b", "c"]);
console.log(set); // Set(3) {'a', 'b', 'c'}

// 方法2:使用map()
let arr1 = [5, 5, 4, 6];
let set1 = new Set();
arr1.map(arrElement => set1.add(arrElement));
console.log(set1); // Set(3) {'a', 'b', 'c'}

合并Set

可以使用Set的构造函数和...运算符来合并两个Set。

let set1 = new Set(["a", "b", "c"]);
let set2 = new Set([1, 2, 3]);

// 合并set1、set2
let bigSet = new Set([...set1, ...set2]);  // Set(6) {'a', 'b', 'c', 1, 2, 3}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值