一、Map
Map对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。
Map与Object区别:
Map默认情况不包含任何键。只包含显式插入的键。
Map的键可以是任意值,包括函数、对象或任意基本类型。NaN也可以作为键
Map中的key是有序的。因此,当迭代的时候,一个Map对象以插入的顺序返回键值。
Map的键值对个数可以轻易地通过Size属性获取
Map是 iterable的,所以可以直接被迭代。
Map在频繁增删键值对的场景下表现更好。
一个Object有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
一个Object的键必须是一个String或是Symbol。
Object 的键值对个数只能手动计算
1、示例
let myMap = new Map();
let keyObj = {};
let keyFunc = function() {};
let keyString = 'a string';
// 添加键
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值");
myMap.size; // 3
// 读取值
myMap.get(keyString); // "和键'a string'关联的值"
myMap.get(keyObj); // "和键keyObj关联的值"
myMap.get(keyFunc); // "和键keyFunc关联的值"
myMap.get('a string');
outpit:
"和键'a string'关联的值"
因为keyString === 'a string'
myMap.get({});
output:
undefined, 因为keyObj !== {}
myMap.get(function() {});
output:
undefined, 因为keyFunc !== function () {}
2、常用方法
myMap.clear()
移除Map对象的所有键/值对 。
myMap.delete(key)
如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false。
随后调用 myMap.has(key) 将返回 false 。
myMap.entries()
返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。
myMap.forEach(callbackFn[, thisArg])
按插入顺序,为 Map对象里的每一键值对调用一次callbackFn函数。
如果为forEach提供了thisArg,它将在每次回调中作为this值。
myMap.get(key)
返回键对应的值,如果不存在,则返回undefined。
myMap.has(key)
返回一个布尔值,表示Map实例是否包含键对应的值。
myMap.keys()
返回一个新的 Iterator对象, 它按插入顺序包含了Map对象中每个元素的键 。
myMap.set(key, value)
设置Map对象中键的值。返回该Map对象。
myMap.values()
返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值 。
myMap[@@iterator]()
返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。
示例
forEach方法按照插入顺序依次对 Map 中每个键/值对执行一次给定的函数
myMap.forEach(callback(value,key,map), thisArg)
thisAgr可以通过传参,改变this指向,如下
let keyString = 'a string';
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值");
var z = new Map();
z.set(1,"test1");
myMap.forEach(function(value,key){
console.log(this.get(1));
}
,z);//thisArg传参为z
output:
test1
test1
test1
3、Map和数组的关系
let kvArray = [["key1", "value1"], ["key2", "value2"]];
使用常规的Map构造函数可以将一个二维键值对数组转换成一个Map对象
let myMap = new Map(kvArray);
myMap.get("key1"); // 返回值为 "value1"
使用Array.from函数可以将一个Map对象转换成一个二维键值对数组
console.log(Array.from(myMap)); // 输出和kvArray相同的数组
更简洁的方法来做如上同样的事情,使用展开运算符
console.log([...myMap]);
或者在键或者值的迭代器上使用Array.from,进而得到只含有键或者值的数组
console.log(Array.from(myMap.keys())); // 输出 ["key1", "key2"]
4、复制和合并
let original = new Map([
[1, 'one']
]);
let clone = new Map(original);
console.log(clone.get(1)); // one
console.log(original === clone); // false. 浅比较 不为同一个对象的引用
对象间的合并
let first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let second = new Map([
[1, 'uno'],
[2, 'dos']
]);
合并两个Map对象时,如果有重复的键值,则后面的会覆盖前面的。
展开运算符本质上是将Map对象转换成数组。
let merged = new Map([...first, ...second]);
console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
和数组的合并
let first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let second = new Map([
[1, 'uno'],
[2, 'dos']
]);
Map对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的。
let merged = new Map([...first, ...second, [1, 'eins']]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
二、Set
对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。et中的元素只会出现一次,即 Set 中的元素是唯一的。
1、常用方法
set的常用方法大部分是和map相似的
set添加元素是用add,mao则用set
let mySet = new Set();
mySet.add("1");
mySet.add(5);
for (let [key, value] of mySet.entries())
console.log(key);
为了使这个方法和Map对象保持相似, 每个值的键和值相等
2、基本集合操作
function isSuperset(set, subset) {
for (let elem of subset) {
if (!set.has(elem)) {
return false;
}
}
return true;
}
function union(setA, setB) {
let _union = new Set(setA);
for (let elem of setB) {
_union.add(elem);
}
return _union;
}
function intersection(setA, setB) {
let _intersection = new Set();
for (let elem of setB) {
if (setA.has(elem)) {
_intersection.add(elem);
}
}
return _intersection;
}
function symmetricDifference(setA, setB) {
let _difference = new Set(setA);
for (let elem of setB) {
if (_difference.has(elem)) {
_difference.delete(elem);
} else {
_difference.add(elem);
}
}
return _difference;
}
function difference(setA, setB) {
let _difference = new Set(setA);
for (let elem of setB) {
_difference.delete(elem);
}
return _difference;
}
//Examples
let setA = new Set([1, 2, 3, 4]),
setB = new Set([2, 3]),
setC = new Set([3, 4, 5, 6]);
isSuperset(setA, setB); // => true
union(setA, setC); // => Set [1, 2, 3, 4, 5, 6]
intersection(setA, setC); // => Set [3, 4]
symmetricDifference(setA, setC); // => Set [1, 2, 5, 6]
difference(setA, setC); // => Set [1, 2]
3、数组去重
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
4、String转set
let text = 'India';
let mySet = new Set(text); // Set {'I', 'n', 'd', 'i', 'a'}
mySet.size; // 5
大小写敏感
new Set("Firefox") // Set(7) [ "F", "i", "r", "e", "f", "o", "x" ]
如果是小写firefox,第二个f将会被去重掉
Array参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
Set参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set
Map参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map