Map对象
Map对象保存键值对,任何值(对象或者原始值)都可以作为一个键或者一个值。 使用JavaScript创建一个Map如下:
let m = new Map();可以向Map里放入键值对:
m.set("aaa",1);
m.set("bbb",2);
m.set("ccc",3);或者利用二维数组初始化:
let m = new Map([["aaa",1],["bbb",2],["ccc",3]])常用方法
let m = new Map();
m.set("aaa",1); //添加键值对
m.has("aaa"); //是否存在key为"aaa":true
m.get("bbb"); // 2
m.delete("ccc"); // 删除key "ccc"注:一个key只能对应一个value,如果重复放入key-value,后面的value会把前面的value替换。
Map对象的相关操作
和Array的转化:
let m = new Map([["aaa",1],["bbb",2],["ccc",3]])
console.log(Array.from(m)); //使用Array.from()可将一个Map对象转化为一个二维键值对数组Map的克隆:
let m = new Map([["aaa",1],["bbb",2],["ccc",3]])
let m1 = new Map(m)
console.log(m===m1); //falseMap的合并:
let m = new Map([
["aaa", 1],
["bbb", 2],
]);
let m1 = new Map([["bbb", 3]]);
let m2 = new Map([...m, ...m1]);
console.log(m2); //{ "aaa" => 1, "bbb" => 3 }后面的value会覆盖前面同key的valueSet对象
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
let s = new Set();
s.add(1);
s.add("abc");
s.add({ aaa: 1 });Set对象的作用:
数组去重
var s = new Set([1, 2, 3, 4, 4]);
[...s]; // [1, 2, 3, 4]取并集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}取交集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}算法实例演示
两数求和:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。解法1:双循环暴力求解 时间复杂度: O(n^2)O(n 2) 空间复杂度: O(1)O(1)
var twoSum = function(nums, target) {
for(let i = 0, len = nums.length;i < len;i++){
// 因为同一元素不允许重复出现,所以从i的下一位开始遍历
for(let j = i + 1;j < len;j++) {
if(nums[i] + nums[j] === target) {
return [i, j];
}
}
}
// 所有样例都是有返回结果的,这里无所谓
return [-1, -1];
};解法2:一次循环,使用HashMap进行记录 时间复杂度:O(n)O(n) 空间复杂度:O(n)O(n)
var twoSum = function(nums, target) {
const map = new Map();
for(let i = 0, len = nums.length;i < len;i++) {
if(map.has(target - nums[i])) {
return [map.get(target - nums[i]), i];
}
map.set(nums[i], i);
}
return [];
};WeakSet
和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。 WeakSet和Set的区别:
区别一:WeakSet中只能存放对象类型,不能存放基本数据类型;
区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收;
上述示例中创建了先一个obj对象,又创建了一个set对象,并且假设向set对象中添加了obj,并且有个索引item1。此时如果使用obj = null 把obj置空,此时由于item1仍然指向0X100,所以obj不会被GC回收。但是如果时weakSet,item1对0X100的引用是弱引用,obj对象则会被回收掉。

WeakSet常见的方法:
add(value):添加某个元素,返回WeakSet对象本身;
delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
has(value):判断WeakSet中是否存在某个元素,返回boolean类型
WeakSet的应用
const personSet = new WeakSet();
class Person {
constructor() {
personSet.add(this);
}
running() {
if (!personSet.has(this)) {
throw Error("该方法只能通过new对象调用");
}
console.log("i an running", this);
}
}
const p = new Person();
p.running(); //i an running Person {}
// p.running.call({ name: "sun" }); //i an running { name: "sun" }
p.running.call({ name: "sun" }); //throw Error("该方法只能通过new对象调用");上述案例中创建一个Person类,Person类中有一个running方法。我们可以通过构造方法创建出来的p调用running方法。此时this指向p。还可以通过call来调用来使Perosn里的this指向 {name:"sun"}。 此时如果有一个需求:不能通过非构造方法创建出来的对象来调用running。此时就可以使用先创建一个WeakSet,在创建对象时会先执行constructor把this存入WeakSet,在调用running时先判断是否存在this。 为啥不用new Set(),因为创建了一个对象p,如果执行P=null;此时的p是不会被销毁的,因为set是强引用。
WeakMap
和Map类型相似的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的。和Map区别
区别一:WeakMap的key只能使用对象,不接受其他的类型作为key;
区别二:WeakMap的key对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;常见的方法
set(key, value):在Map中添加key、value,并且返回整个Map对象;
get(key):根据key获取Map中的value;
has(key):判断是否包括某一个key,返回Boolean类型;
delete(key):根据key删除一个键值对,返回Boolean类型;
WeakMap的应用
const obj1 = {
name: "sun",
age: 20,
};
function obj1NameFn1() {
console.log("obj1namefn1执行");
}
function obj1NameFn2() {
console.log("obj1namefn2执行");
}
function objAgeFn1() {
console.log("obj1agefn1执行");
}
function objAgeFn2() {
console.log("obj1agefn2执行");
}
const obj2 = {
height: 190,
};
function obj2HeightFn1() {
console.log("obj2heightfn1执行");
}
function obj2HeightFn2() {
console.log("obj2heightfn2执行");
}
// 需求:监听对象的变化执行相应操作
// 1,创建weakMap
const weakMap = new WeakMap();
// 2,收集依赖结构
// 2.1对obj1收集的数据结构
const map1 = new Map();
map1.set("name", [obj1NameFn1, obj1NameFn2]);
map1.set("age", [objAgeFn1, objAgeFn2]);
weakMap.set(obj1, map1);
// 2.2对obj2收集的数据结构
const map2 = new Map();
map2.set("height", [obj2HeightFn1, obj2HeightFn2]);
weakMap.set(obj2, map2);
// 3,如果obj.name发生了变化
// proxy/Object.defineProterty
Object.defineProperty(obj1, "name", {
set: function () {
const targetMap = weakMap.get(obj1);
const fns = targetMap.get("name");
fns.forEach((ele) => {
ele();
});
},
});
obj1.name = "lebron";
// obj1namefn1执行
// obj1namefn2执行