Map对象

Map对象    兼容性ES6  Edge12

Map 对象保存键值对,并且能够记住键的原始插入顺序。

任何值(对象或者原始值) 都可以作为一个键或一个值。

一个Map对象在迭代时会根据对象中元素的插入顺序来进行 — 一个  for...of 循环在每次迭代后会返回一个形式为[key,value]的数组。所以说一定要知道顺序,这样在进行for...of迭代时,得到数组值的顺序就可以确定了。Set对象同理。

[[key,value], [key,value], [key,value]]

Objects 和 Maps 类似的是,它们都允许你按键存取一个值、删除键、检测一个键是否绑定了值

 Maps 和 Objects 有一些重要的区别,在下列情况里使用 Map 会是更好的选择:

       

Map

Object

意外的键Map 默认情况不包含任何键。只包含显式插入的键。

一个 Object 有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

注意: 虽然 ES5 开始可以用 Object.create(null) 来创建一个没有原型的对象,但是这种用法不太常见。

键的类型一个 Map的键可以是任意值,包括函数、对象或任意基本类型。一个Object 的键必须是一个 String 或是Symbol
键的顺序

Map 中的 key 是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。

一个 Object 的键是无序的

注意:自ECMAScript 2015规范以来,对象确实保留了字符串和Symbol键的创建顺序; 因此,在只有字符串键的对象上进行迭代将按插入顺序产生键。

Size Map 的键值对个数可以轻易地通过size 属性获取Object 的键值对个数只能手动计算
迭代Map 是 iterable 的,所以可以直接被迭代。迭代一个Object需要以某种方式获取它的键然后才能迭代。
性能

在频繁增删键值对的场景下表现更好。

在频繁添加和删除键值对的场景下未作出优化。

 

键的相等

NaN 是与 NaN 相等的(虽然 NaN !== NaN),剩下所有其它的值是根据 === 运算符的结果判断是否相等。

ECMAScript规范中,-0+0被认为是相等的,尽管这在早期的草案中并不是这样

引用值判断索引是否相等,原始值判断值是否相等

new Map()设置属性及值

(1)接受一个数组,数组中的每项都是由key值和value值组成的数组——(二维数组)

let key1 = "a", key2 = "b", key3 = "c";
let value1 = 1, value2 = 2, value3 = 3;
let map = new Map([
  [key1,value1],
  [key2,value2],
  [key3,value3]
])
Map(3) {"a" => 1, "b" => 2, "c" => 3}

(2)接受一个迭代对象(iterable对象)组成,其元素为键值对(两个元素的数组) 每个键值对都会添加到新的 Map。null 会被当做 undefined。 

let key1 = "a", key2 = "b", key3 = "c";
let value1 = 1, value2 = 2, value3 = 3;
let map = new Map([
  [key1,value1],
  [key2,value2],
  [key3,value3]
])
接受一个Map对象
console.log(new Map(map)); Map(3) {"a" => 1, "b" => 2, "c" => 3}

接受一个Map对象的entries()执行结果
console.log(new Map(map.entries()));  Map(3) {"a" => 1, "b" => 2, "c" => 3}

let iterable = {};
iterable[Symbol.iterator] = function* () {
  yield ["a1",1];
  yield ["b1",2];
  yield ["c1",3];
}
接受一个生成器的iterable对象
console.log(new Map(iterable))  Map(3) {"a1" => 1, "b1" => 2, "c1" => 3}

 克隆Map对象

以下克隆Map对象的方式,可以深度克隆。注意看以下代码中的注释

引用值的=赋值,是将地址直接赋值,所以操作其中一个,会影响另一个引用值。但是其他对引用值的操作,是开辟新的空间地址,两者一般不受影响。

let arr = [1,2,3];
let arr1 = [4,5,6];
let keyObj = {};
let original = new Map([
  [1, arr1],
  [keyObj,"abc"],
  [arr,arr1]
]);
 
let clone = new Map(original);
// new Map的方式进行克隆,实际上就是在代码中再写一个Map对象
clone = new Map([
  [1, arr1],
  [keyObj,"abc"],
  [arr,arr1]
]);
// 不管是新设置还是修改或者删除,都是对Map对象的操作
// 对original Map对象的操作,不影响clone Map对象
original.set(2,'two');
original.set(1,"1");  
original.set(keyObj,"xyz"); 
// 修改后的original Map对象
original = new Map([
  [1, "1"],
  [keyObj,"xyz"],
  [arr,arr1],
  [2,'two']
]);
// 但是对变量的修改,会影响到该变量所在的Map对象
arr1.push(7);
 
console.log(original.get(keyObj),clone.get(keyObj));  //xyz abc
console.log(original.get(arr),clone.get(arr));  //[4, 5, 6, 7]  [4, 5, 6, 7]
console.log(original === clone);  //false.  不为同一个对象的引用

相关属性

1、Map.prototype  Map对象原型

Map 实例继承自Map.prototype。你可以使用这个构造函数的原型对象来给所有的Map实例添加属性或者方法。

2、size属性 Map.prototype.size

与Set方法的size属性一样:size 属性的值是一个整数,表示 Map 对象有多少个键值对。size 是只读属性,用set 方法修改size返回 undefined,即不能改变它的值。
3、Map.prototype.constructor  Map的构造函数

返回一个函数,它创建了实例的原型。默认是Map函数。

相关方法

1、set方法

(1)set() 方法为 Map 对象添加或更新一个指定了键(key)和值(value)的(新)键值对。

(2)因为 Set() 方法返回 Map 对象本身,所以你可以像下面这样链式调用它。

(3)键可以是一个值,也可以是一个变量

let myMap = new Map();
myMap.set("a", 1).set("b", 2).set("c",3);
console.log(myMap); //Map(3) {"a" => 1, "b" => 2, "c" => 3}

 

2、get方法

返回一个 Map 对象中与指定键相关联的值,如果找不到这个键则返回 undefined

let myMap = new Map();
myMap.set("a", 1).set("b", 2).set("c",3);
console.log(myMap.get("a")); //1

3、forEach方法

forEach 仅仅是对 Map 对象中的每一个元素执行一遍 callback 函数,它不会返回任何值。

 回调函数接收三个参数:value key map 即每次回调执行的value值、key值、Map副本对象。

我需要熟悉一个词:数组中的item index 与 此处的value key。item index 与value key其实是对应的。

let myMap = new Map();
myMap.set("a", 1).set("b", 2).set("c",3);
myMap.forEach((value, key, thisArg) => {
  console.log(thisArg); //Map(3) {"a" => 1, "b" => 2, "c" => 3}
})

4、keys方法

keys() 返回一个存在引用关系的 MapIterator对象,该对象的[[Entries]]属性是由key键值组成的Iterator对象

        let myMap = new Map();
        myMap.set("name", "zhuzhu")
             .set(23, 24)
             .set(false, true)
             .set(["1",2], ["js","html","css"])
             .set({}, {a:1,b:2});

        console.log(myMap.keys())

5、values方法

返回一个MapIterator对象,该对象的[[Entries]]属性是一个由value值组成的Iterator对象

        let myMap = new Map();
        myMap.set("name", "zhuzhu")
             .set(23, 24)
             .set(false, true)
             .set(["1",2], ["js","html","css"])
             .set({}, {a:1,b:2});
        let valuesMap = myMap.values()
        console.log(valuesMap)
        valuesMap.next()
        console.log(valuesMap.next())

6、entries方法(Map对象的[Symbol.iterator]属性也指向该方法)

返回一个MapIterator对象,该对象的中的[[Entries]]属性,是由每项{key:key值,value:value值}的对象,组成的Iterator对象。

MapIterator对象可以调用next方法

        let myMap = new Map();
        myMap.set("name", "zhuzhu")
             .set(23, 24)
             .set(false, true)
             .set(["1",2], ["js","html","css"])
             .set({}, {a:1,b:2});
        let entriesMap = myMap.entries();
        console.log(entriesMap)
        console.log(entriesMap.next())

调用next方法的结果:value属性是一个数组,0项是对应的key,1项是对应的value值

7、has方法

方法has() 返回一个Boolean 值,用来表明map 中是否存在指定元素。

key 必填. 用来检测是否存在指定元素的键值.

        let myMap = new Map();
        myMap.set("name", "zhuzhu")
             .set(23, 24)
             .set(false, true)
             .set(["1",2], ["js","html","css"])
             .set({}, {a:1,b:2});
        console.log(myMap.has(["1",2]));  false
        console.log(myMap.has(23));    true

上面代码中 引用属性是要找同一个地址的,原始值可以找到该属性。

8、delete方法

delete() 方法用于移除 Map 对象中指定的元素。

key 必填。从 Map 对象中移除的元素的键。

如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false

9、clear方法

clear()方法会移除Map对象中的所有元素。清空Map对象。

var myMap = new Map();
myMap.set("bar", "baz");
myMap.set(1, "foo");

myMap.size;       // 2
myMap.has("bar"); // true

myMap.clear();

myMap.size;       // 0
myMap.has("bar")  // false

注意的事项

1、关于键值

NaN 是与 NaN 相等的(虽然 NaN !== NaN 且 NaN != NaN),剩下所有其它的值是根据 === 运算符的结果判断是否相等。

 (1)NaN作为键值

        myMap.set(NaN, "aaa");
        console.log(myMap.get(NaN));   aaa
        console.log(myMap.get(Number("abc")));  aaa

上面代码中值为NaN的键,其对应的value都是aaa。

(2)undefined作为键值

        let key;
        myMap.set(undefined, "aaa");
        console.log(myMap.get(undefined)); aaa
        console.log(myMap.get(key));   aaa

上面代码中值为undefined的键,其对应的value都是aaa。

(3) null作为键值

        let key = null;
        myMap.set(null, "aaa");
        console.log(myMap.get(null)); aaa
        console.log(myMap.get(key));  aaa

(4)字符串、数字、布尔值作为键值

 同样只要键值=== 其value值都是相同的,即获取的是同一个键。

(5)对象、数组、函数

引用值,如果指向的地址是同一个地址,获取的也是同一个键;如果不是同一个地址,获取的就不是同一个键。

        let key = {};
        let key1 = key;
        myMap.set(key, "aaa");
        console.log(myMap.get({}));  undefined
        console.log(myMap.get(key)); aaa
        console.log(myMap.get(key1)) aaa

2、for...of迭代Map对象

for...of可以迭代Map对象和Set对象,已经调用他们的方法得到的MapIterator和SetIterator对象,所以Map和Set是有序的。此处区别于Object对象

 for...of 循环在每次迭代后会返回一个形式为[key,value]的数组。

        let myMap = new Map();
        myMap.set("name", "zhuzhu")
             .set(23, 24)
             .set(false, true)
             .set(["1",2], ["js","html","css"])
             .set({}, {a:1,b:2});

        for(keyValue of myMap){
            console.log(keyValue)  
        }

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值