const m = new Map();

如果想在创建映射实例的同时初始化,可以传入可迭代对象(需包含键/值对数组),可迭代对象中的键/值对会按照迭代顺序插入到映射实例中。

const m1 = new Map([
	["key1", "val1"],
	["key2", "val2"],
	["key3", "val3"]
]);
console.log(m1.size); // 3
const m2 = new Map({
	[Symbol.iterator]: function* () {
		yield ["key1", "val1"];
		yield ["key2", "val2"];
		yield ["key3", "val3"];
});
console.log(m2.size); // 3
const m3 = new Map([[]]);
console.log(m3.has(undefined)); // true
console.log(m3.get(undefined)); // undefined

设置键/值对

可以使用 set() 方法添加或更新键/值对,set() 方法返回映射实例,因此可以把多个操作连接起来。

可以使用任意 JavaScript 数据类型作为键,注意键不能重复。

const m = new Map().set("key1", "val1");
m.set("key2", "val2")
 .set("key3", "val3");
console.log(m.size); // 3

查询键/值对

可以通过 size 属性获取键/值对数量, has() 方法查询键/值对是否存在,get() 方法获取键/值对的值。

const m = new Map();
console.log(m.size); // 0
console.log(m.has("firstName")); // false
console.log(m.get("firstName")); // undefined
m.set("firstName", "Matt")
 .set("lastName", "Frisbie");
console.log(m.size); // 2 
console.log(m.has("firstName")); // true
console.log(m.get("firstName")); // Matt

删除键/值对

可以使用 delete() 删除指定键/值对,clear() 清空所有键/值对。

const m = new Map()
	.set("firstName", "Matt")
	.set("lastName", "Frisbie");
m.delete("firstName"); // 只删除这一个键/值对
console.log(m.size); // 1
console.log(m.has("firstName")); // false
console.log(m.has("lastName")); // true
m.clear(); // 清除所有键/值对
console.log(m.size); // 0
console.log(m.has("firstName")); // false
console.log(m.has("lastName")); // false

顺序与迭代

Map 映射实例会维护键/值对的插入顺序,因此可以根据插入顺序执行迭代操作。

for…of

let myMap = new Map([['key1','val1']]);
for(let ele of myMap) {
    console.log(ele);
// ['key1', 'val1']

forEach()

forEach(callback, opt_thisArg) 方法可以依次迭代每个键/值对,可选的第二个参数用于重写回调内部 this 的值。

const m = new Map([
	["key1", "val1"],
	["key2", "val2"],
	["key3", "val3"]
]);
m.forEach((val, key) => 
	console.log(`${key} -> ${val}`));	
// key1-> val1
// key2-> val2
// key3-> val3

keys()

keys() 返回以插入顺序生成键的迭代器。

const m = new Map([
	["key1", "val1"],
	["key2", "val2"],
	["key3", "val3"]
]);
for (let key of m.keys()) {
  	console.log(key);
// key1
// key2
// key3

values()

values() 返回以插入顺序生成值的迭代器。

const m = new Map([
	["key1", "val1"],
	["key2", "val2"],
	["key3", "val3"]
]);
for (let key of m.values()) {
  	console.log(key);
// value1
// value2
// value3

entries()

映射实例可以提供一个迭代器(Iterator),能以插入顺序生成 [key, value] 形式的数组。

可以通过 entries() 方法(或者 Symbol.iterator 属性)获取键/值对迭代器。

const m = new Map([
	["key1", "val1"],
	["key2", "val2"],
	["key3", "val3"]
]);
console.log(m.entries === m[Symbol.iterator]); // true
for (let pair of m.entries()) {
	console.log(pair);
// [key1, val1]
// [key2, val2]
// [key3, val3]
for (let pair of m[Symbol.iterator]()) {
  	console.log(pair);
// [key1, val1]
// [key2, val2]
// [key3, val3]

entries() 是默认迭代器,所以映射实例可以使用扩展操作转换为数组。

const m = new Map([
	["key1", "val1"],
	["key2", "val2"],
	["key3", "val3"]
]);
console.log([...m]); 
// [[key1, val1], [key2, val2], [key3, val3]]

Map 与数组

数组转 Map

const kvArray = [['key1', 'value1'], ['key2', 'value2']];
const myMap = new Map(kvArray);

Map 转数组

(1)Array.from

const kvArray = [['key1', 'value1'], ['key2', 'value2']];
const myMap = new Map(kvArray);
console.log(Array.from(myMap));

(2)扩展操作符

console.log([...myMap]);

Map 与 Object

Object 可以满足大部分 Web 开发需求,如果涉及大量的键/值对增删操作,推荐 Map。

Object 只能使用数值(最终会转为字符串)、字符串或符号作为键,而 Map 可以使用任意 JavaScript 数据类型作为键。

Map 内部使用 SameValueZero 比较操作(ECMAScript 规范内部定义,语言中不能使用),基本上相当于使用严格对象相等的标准来检查键的匹配性。

const m = new Map();
const functionKey = function() {};
const symbolKey = Symbol();
const objectKey = new Object();
m.set(functionKey, "functionValue");
m.set(symbolKey, "symbolValue");
m.set(objectKey, "objectValue");
console.log(m.get(functionKey)); // functionValue
console.log(m.get(symbolKey)); // symbolValue
console.log(m.get(objectKey)); // objectValue
// SameValueZero 比较意味着独立实例不冲突
console.log(m.get(function() {})); // undefined

对象及其他“集合”类型在映射中用作键或值时,使用的是地址。

const m = new Map();
const objKey = {},
      objVal = {},
      arrKey = [],
      arrVal = [];
m.set(objKey, objVal);
m.set(arrKey, arrVal);
objKey.foo = "foo";
objVal.bar = "bar";
arrKey.push("foo");
arrVal.push("bar");
console.log(m.get(objKey)); // {bar: "bar"}
console.log(m.get(arrKey)); // ["bar"]

SameValueZero 比较可能导致意想不到的冲突。

SameValueZero 比较时,NaN === NaN,+0 === -0
const m = new Map();
const a = 0/"", // NaN
      b = 0/"", // NaN
      pz = +0,
      nz = -0;
console.log(a === b); // false
console.log(pz === nz); // true
m.set(a, "foo");
m.set(pz, "bar");
console.log(m.get(b)); // foo
console.log(m.get(nz)); // bar

Object 和 Map 的工程级实现在浏览器间存在明显差异,但存储单个键/值对所占用的内存数量都会随键的数量线性增加。

给定固定大小的内存,Map 大约可以比 Object 多存储 50% 的键/值对。

向 Object 和 Map 中插入新键/值对的消耗大致相当,插入 Map 一般会稍微快点。

插入速度不会随着键/值对数量增加而线性增加。

如果代码涉及大量插入操作,那么显然 Map 的性能更佳。

从大型 Object 和 Map 中查找键/值对的性能差异极小,但如果只包含少量键/值对,Object 有时速度更快。

在把 Object 当成数组使用的情况下(比如使用连续整数作为属性),浏览器引擎可以进行优化,在内存中使用更高效的布局。

查找速度不会随着键/值对数量增加而线性增加。

如果代码涉及大量查找操作,那么可能选择 Object 更好一些。

使用 delete 删除 Object 属性的性能一直以来饱受诟病,目前在很多浏览器中仍然如此。

为此,出现了一些伪删除对象属性的操作,包括把属性值设置为 undefined 或 null,这是一种不适宜的折中。

对大多数浏览器引擎来说,Map 的 delete() 操作比插入和查找更快。

如果代码涉及大量删除操作,那么应该选择 Map。

Hash Map通常在JavaScript中作为一个简单的来存储键值对的地方。然而,Object并不是一个真正的哈希映射,如果使用不当可能会带来潜在的问题。而且JavaScript可能不提供本地哈希映射(至少不是跨浏览器兼容的),有一个更好的声明对象属性的方法。 Hash Map的简单实现: var hashMap = { Set : function(key,value){this[key] = value}, Get : function(key){return this[key]}, Contains : function(key){return this.Get(key
new Map() —— 创建 mapmap.set(key, value) —— 根据键存储值。 map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined。 map.has(key) —— 如果 key 存在则返回 true,否则返回 false。 map.delete(key) ——
前文的学习过程中,我们已经了解了非常多的数据类型,包括基础类型、复杂的对象、顺序存储的数组等。为了更好的应对现实生产中的情况,我们还需要学习更多的数据类型:映射()和集合()。是一个键值对构成的集合,和对象非常相似,都是由一个名称对应一个值组成的。和对象区别在于,的键可以采用任何类型的数据,而对象只能使用字符串作为属性名称。举个例子: 代码执行结果:方法返回本身。虽然方式同样可以访问映射的键值对,但是不推荐使用这种方式,因为它会造成歧义。我们可以看下面的案例: 这里就出现了一个奇怪的结果:不仅使用键还可以使
使用new关键字和Map构造函数可以创建一个空映射: const m = new Map(); 如果想在创建的同时初始化实例,可以给Map构造函数传入一个可迭代对象,需要包含键/值对数组。可迭代对象中的每个键/值对都会按照迭代顺序插入到新映射实例中: // 使用嵌套数组初始化映射 const m1 = new Map([ ["key1", "val1"], ["key2", "val2"], ["key3", "val3"] alert(m1.size); // 3 使用map和computed的巧妙写法 otherFiledList是已选数据,fieldList是可选数据。已选数据是可选数据构成的 <div v-for="(item,index) in fieldList" :key="index" @click.native="fieldSelect(item, selectMap[item.name])"> <i v-show="selectMap[item.n 基本类型 - 基本类型、基本类型 - 包装对象返回 true 包装对象 - 包装对象返回 false 缓存中取的包装对象比较返回 true(原因是 JVM 缓存部分基本类型常用的包装类对象,如 Integer -128 ~ 127 是被缓存的,内存地址相同。注意:使用valueof()方法创建的对象才会缓存) 使用 equals() 比较
ES6中的Map和Filter都是Array的高阶函数,它们可以让开发者更加方便地操作数组数据。 Map函数的作用是将数组中的每个元素通过一个函数映射成另一个元素。Map的返回值是一个新的数组,该数组的每个元素都是原数组对应元素通过指定函数映射后的结果。 例如,下面的代码使用Map将一个数组中的每个元素加1: ```javascript const arr = [1, 2, 3]; const newArr = arr.map(x => x + 1); console.log(newArr); // [2, 3, 4] Filter函数的作用是对数组中的元素进行过滤,只返回符合条件的元素。Filter的返回值是一个新的数组,只包含原数组中符合条件的元素。 例如,下面的代码使用Filter从一个数组中筛选出所有偶数: ```javascript const arr = [1, 2, 3, 4, 5]; const evenArr = arr.filter(x => x % 2 === 0); console.log(evenArr); // [2, 4] 因此,Map和Filter的主要区别在于它们的作用不同:Map用于映射每个元素,而Filter用于过滤出符合条件的元素。此外,Map会返回一个新的数组,而Filter只返回原数组中符合条件的元素。