文章目录
Map
Map对象保存键值对(Hash结构)。任何值(对象或者原始值)都可以作为一个键或一个值。构造函数的参数是一个iterable对象,其元素值为键值对。每个键值都会添加到新的Map。null会被当做undefined。
var map = new Map([iterable]);
初始化示例。
- 对一个键多次赋值,则会覆盖
- 键可以是任何值。
- 同Object.is()方法采用的算法,键的判断方法类似。
- 只有对同一个对象的引用,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
相同点
- 都允许按键存取一个值、删除键、检测一个键是否绑定了值。
不同点
- | Object | Map |
---|---|---|
键 | 字符串/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数组
- 使用扩展运算符
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上设置一个键值对需要在这两个数组的最后加上键和值,从而使得键和值在两个数组中相对应。当从中获取一个值,必须先遍历键找到这个键对应的位置,再从这个位置去值所在的数组中查找对应的值。
而缺点便是:
- 赋值和搜索操作都是O(n)的时间复杂度,因为这两个操作都需要遍历全部整个数组来进行匹配。
- 可能会导致内存泄露,因为数组会一直引用着每一个键和值。使垃圾回收算法不能回收处理他们,即使没有其他任何的引用。
相对来说,原生的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