整理学习——Map和WeakMap

本文详细介绍了Map和WeakMap的区别、属性、实例方法以及它们之间的转换,强调了WeakMap的弱引用特性及其在内存管理中的优势。通过实例展示了如何在JavaScript中操作和使用这两个数据结构。
摘要由CSDN通过智能技术生成

Map

Map对象保存键值对(Hash结构)。任何值(对象或者原始值)都可以作为一个键或一个值。构造函数的参数是一个iterable对象,其元素值为键值对。每个键值都会添加到新的Map。null会被当做undefined。

var map = new Map([iterable]); 

初始化示例。

  1. 对一个键多次赋值,则会覆盖
  2. 键可以是任何值。
  3. 同Object.is()方法采用的算法,键的判断方法类似。
  4. 只有对同一个对象的引用,Map结构才将其视为同一个键。(键实际上是与内存地址绑定,若内存地址不同,则为两个键)
var item1 = [
	[1,"2"],
	[1, 1],
	["1", "str"]
];
var map1 = new Map(item1);
map1.set(2,2);

//直接在构造函数赋值相当于
var map1 = new Map();
item1.forEach([key,value] => map1.set(key, value));

对比Object

相同点

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

不同点

-ObjectMap
字符串/Symbols任意值(包括函数、对象、基本类型)
键值
有序
非有序有序,按插入顺序返回
键值对
个数
手动计算size对象直接获取
迭代
方式
先获取键数组,再迭代可直接迭代
原型有自己的原型,原型链上的键名有可能和设置的对象上的键名产生冲突通过set和get,避免了修改原型的键名
性能优势场景\相对来说,在涉及频繁增删键值对的场景更有优势

属性

Map.length

0

get Map[@@species]

本构造函数用于创建派生对象。

Map.prototype

表示Map构造器的原型。允许添加属性从而应用于所有Map对象

Map实例

所有Map对象实例都会集成Map.prototype

var arr1 = ["a"],
	arr2 = ["a"];
var item = [
	[1,1],
	["str", "str"],
	[arr1, "arr1"]
];
var map = new Map(item);

属性

Map.prototype.constructor

返回一个创建实例的原型的函数。默认是Map()

Map.prototype.size

返回Map对象的键/值对的数量。

console.log(map.size);
//Output: 3

方法

Map.prototype.clear()

移除Map对象的所有键值对

console.log(map);
//Output: Map(3) {1 => 1, "str" => "str", Array(1) => "arr1"}
map.clear();
console.log(map)
//Output: Map(0) {}

Map.prototype.delete(key)

如果Map对象中存在key的键,则移除它并返回true;若不存在则返回false

map.delete(arr1);
//result: true
console.log(map);
//Output: Map(2) {1 => 1, "str" => "str"}
map.delete(arr1);
//result: false

Map.prototype.entries()

返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的[key, value]数组

map.entries();
//result: MapIterator {1 => 1, "str" => "str", Array(1) => "arr1"}

Map.prototype.forEach(callbackFn[,thisArg])

按插入顺序,为Map对象里的每一个键值对调用一次callbackFn函数。如果为其提供了thisArg参数,那么这个thisArg会是callbackFn的this值

map.forEach(function(x,y){
	console.log(x,y);
});
/*Output:
1 1
str str
arr1 ["a"]
*/
var arg = "arg";
map.forEach(function(){
	console.log(this);
}, arg);
/*Output:
String {"arg"}
String {"arg"}
String {"arg"}
*/

Map.prototype.get(key)

返回键对应的值。
若不存在该键,则返回undefined

map.get(1);
//result: 1
map.get(arr2);
//result: undefined

Map.prototype.has(key)

返回一个布尔值,表示Map实例是否包含键。

map.has(1);
//result: true
map.has(arr2);
//result: false

Map.prototype.keys()

返回一个新的Iterator对象,它包含了Map实例对象的每组键值对中的,按插入顺序排序。

map.keys();
//result: MapIterator {1, "str", Array(1)}

Map.prototype.set(key, value)

设置Map对象中键的值(修改或者新建)。返回该Map对象。

map.set(arr2, "arr2");
console.log(map);
//result: Map(4) {1 => 1, "str" => "str", Array(1) => "arr1", Array(1) => "arr2"}

Map.prototype.values()

返回一个新的Iterator对象,它包含了Map实例对象的每组键值对中的,按插入顺序排序。

map.values();
//result: MapIterator {1, "str", "arr1", "arr2"}

Map.prototype@@iterator

返回一个新的Iterator对象,它包含了Map对象中每个元素的**[key, value]数组**。

var iterator = map[Symbol.iterator]();
for(let i of iterator){
	console.log(i)
}
/*Output:
[1, 1]
["str", "str"]
[Array(1), "arr1"]
[Array(1), "arr2"]
*/

遍历

map.keys()map.values()map.entries()map.forEach(callbackFn[,thisArg])

与其他数据结构的互相转换

以以下代码为例

var item = [
	[1,1],
	["str", "str"]
];
var map = new Map(item);

Map2数组

  1. 使用扩展运算符
    var  arr = [...map];
    console.log(arr);
    //Output: [ [1,1],["str", "str"] ]
    

数组2Map

var map = new Map(item);

Map2对象

function map2Object(map){
	let obj = {};
	for(let [key, value ] of map){
		obj[key] = value;
	}
	return obj;
}
var obj = map2Object(map);
console.log(obj)
//Output: {1: 1, str: "str"}

对象2Map

function object2Map(obj){
	var map = new Map();
	for(let key in obj){
		map.set(key, obj[key]);
	}
	return map;
}
var obj = Object.create({
	1: 1,
	str: "str",
	boo: true
});
var map = object2Map(obj);
console.log(map);
//Output: Map(3) {"1" => 1, "str" => "str", "boo" => true}

Map2JSON

function map2Json(map){
	//先判断所有的键是否不是Object类型(包括数组)
	function checkKeyStr(map){
		let keys = map.keys();
		for(let k of keys){
			let type = typeof k;
			if( type == "object"){
				return false;
			}
		}
		return true;a
	}
	if( checkKeyStr(map) ){
		return JSON.stringify(mapToObj(map))
	}
	else{
		return JSON.stringify([...map]);
	}
}

JSON2Map

function json2Map(jsonStr){
	var source = JSON.parse(jsonStr);
	if(Array.isArray(source)){
		return new Map(source);
	}
	else{
		object2Map(source);
	}
}

WeakMap

WeakMap对象是一组键值对的集合,其中的键是弱引用的,必须为对象,而值可以是任意的。

var wm = new WeakMap([iterable])

iterable是一个二元数组或者其他可迭代的且其元素是键值对的对象。每个键值对会添加到新的WeakMap里。null会被当做undefined。
不过WeakMap的键只能是Object类型。原始数据类型是不能作为key的。

由来

在JavaScript,一个Map接口可以通过四个函数来操作两个数组(一个是键、一个是值)来实现。在这种Map上设置一个键值对需要在这两个数组的最后加上键和值,从而使得键和值在两个数组中相对应。当从中获取一个值,必须先遍历键找到这个键对应的位置,再从这个位置去值所在的数组中查找对应的值。
而缺点便是:

  1. 赋值和搜索操作都是O(n)的时间复杂度,因为这两个操作都需要遍历全部整个数组来进行匹配。
  2. 可能会导致内存泄露,因为数组会一直引用着每一个键和值。使垃圾回收算法不能回收处理他们,即使没有其他任何的引用。

相对来说,原生的WeakMap的键都是弱引用,所以这个键在没有其他引用存在时,垃圾回收能正确进行,映射的key只有在其没有被回收时才是有效的。
因此,WeakMap的key是不可枚举的。

属性

WeakMap.length

0

WeakMap.prototype

WeakMap构造器的原型。允许添加属性到所有的WeakMap对象。

WeakMap实例

以以下代码为例

var obj = {},
	objFn = function(){},
	objWin = window,
	objInit = {},
	obj1 = {};
var wm = new WeakMap([
	[objInit, 3],
	[obj1, 5]
]);
属性
WeakMap.prototype.constructor

返回创建WeakMap实例的原型函数。WeakMap函数时默认的。

方法
WeakMap.prototype.delete(key)

移除key的关联对象。执行后WeakMap.prototype.has(key)返回false。

wm.delete(obj1);
//result: true
wm.delete(obj1);
//result: false
WeakMap.prototype.get(key)

返回key关联对象,或者undefined(没有key关联对象时)。

wm.get(objInit);
//result: 3
wm.get(obj1);
//result: undefined
WeakMap.prototype.has(key)

根据是否有key关联对象返回一个Boolean值。

wm.has(objInit);
//result: true
wm.has(obj1);
//result: false
WeakMap.prototype.set(key, value)

在WeakMap中设置一组关联对象,返回这个WeakMap对象。

wm.set(obj,4);
wm.set(objWin, "str");
wm.set(objFn,true);
//result: WeakMap {Window => "str", {…} => 4, ƒ => true, {…} => 3}

参考地址:
http://caibaojian.com/es6/set-map.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值