Skip to content

ES6

模版字符串

标签函数^标签

标签函数可以直接跟在模版字符串前面

javascript
tagFn`hello ${name}`

下面两个书写方式等价

javascript
function tagFn(arg1, arg2, arg3){
  // ...
}

// tag 函数
tagFn`I'm ${name}. I'm ${age} years old.`

tagFn(["I'm ", ". I'm ", " years old."], name, age)

内置的标签函数

String.raw

Map

Map

Map 是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。

Object对象的键名会通过toString方法转化为字符串类型

在访问对象成员时,键名有空格时不能采用点访问,例如data.ab c

需要采用data['ab c']的形式来访问

Map方法和属性如下:

  • new Map() —— 创建 map。
  • map.set(key, value) —— 根据键存储值。
  • map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined
  • map.has(key) —— 如果 key 存在则返回 true,否则返回 false
  • map.delete(key) —— 删除指定键的值。
  • map.clear() —— 清空 map。
  • map.size —— 返回当前元素个数。
javascript
const map = new Map();

map.set('1', 'str1');   // 字符串键
map.set(1, 'num1');     // 数字键
map.set(true, 'boolean1'); // 布尔值键
map.set({name:'alice'}, 123) // 对象

// 还记得普通的 Object 吗? 它会将键转化为字符串
// Map 则会保留键的类型,所以下面这两个结果不同:
alert( map.get(1)   ); // 'num1'
alert( map.get('1') ); // 'str1'

alert( map.size ); // 3

脚注^1

Map 使用 SameValueZero 算法来比较键是否相等。它和严格等于 === 差不多,但区别是 NaN 被看成是等于 NaN。所以 NaN 也可以被用作键。

这个算法不能被改变或者自定义。

链式调用

每一次 map.set 调用都会返回 map 本身,所以我们可以进行“链式”调用:

javascript
map.set('1', 'str1')
  .set(1, 'num1')
  .set(true, 'boolean1');

Map 迭代

如果要在 map 里使用循环,可以使用以下三个方法:

  • map.keys() —— 遍历并返回一个包含所有键的可迭代对象,
  • map.values() —— 遍历并返回一个包含所有值的可迭代对象,
  • map.entries() —— 遍历并返回一个包含所有实体 [key, value] 的可迭代对象,for..of 在默认情况下使用的就是这个。
javascript
const recipeMap = new Map([
  ['one', 100],
  ['two', 250],
  ['three', 300]
]);

// 遍历所有的键
for (let vegetable of recipeMap.keys()) {
  alert(vegetable); // one, two, three
}

// 遍历所有的值
for (let amount of recipeMap.values()) {
  alert(amount); // 100, 250, 300
}

// 遍历所有的实体 [key, value]
for (let entry of recipeMap) { // 与 recipeMap.entries() 相同
  alert(entry); // 500 (and so on)
}

迭代的顺序与插入值的顺序相同。与普通的 Object 不同,Map 保留了此顺序。

Map 有内建的 forEach 方法,与 Array 类似

javascript
// 对每个键值对 (key, value) 运行 forEach 函数
recipeMap.forEach( (value, key, map) => {
  alert(`${key}: ${value}`); // cucumber: 500 etc
});

Object.entries:从对象创建 Map

当创建一个 Map 后,我们可以传入一个带有键值对的数组(或其它可迭代对象)来进行初始化。

javascript
// 键值对 [key, value] 数组
const map = new Map([
  ['1',  'str1'],
  [1,    'num1'],
  [true, 'boolean1']
]);

alert( map.get('1') ); // str1

如果我们想从一个已有的普通对象(plain object)来创建一个 Map,那么我们可以使用内建方法 Object.entries(obj),该方法返回对象的键/值对数组,该数组格式完全按照 Map 所需的格式。

javascript
const obj = {
  name: "alice",
  age: 30
};

const map = new Map(Object.entries(obj));

alert( map.get('name') ); // alice

这里,Object.entries 返回键/值对数组:[ ["name","John"], ["age", 30] ]。即为 Map 所需要的格式。

Object.fromEntries:从 Map 创建对象

Object.fromEntries 方法的作用是相反的:给定一个具有 [key, value] 键值对的数组,它会根据给定数组创建一个对象

javascript
const prices = Object.fromEntries([
  ['cap', 1],
  ['desk', 2],
  ['food', 4]
]);

// 现在 prices = { cap: 1, desk: 2, food: 4 }

alert(prices.cap); // 1

可以使用 Object.fromEntriesMap 得到一个普通对象(plain object)

javascript
const map = new Map();
map.set('cap', 1);
map.set('desk', 2);
map.set('food', 4);

const obj = Object.fromEntries(map.entries()); // 创建一个普通对象(plain object)(*)

// 完成了!
// obj = { cap: 1, desk: 2, food: 4 }

alert(obj.cap); // 1

同样,也可以省略掉.entires()

javascript
const obj = Object.fromEntries(map); // 省掉 .entries()

因为 Object.fromEntries 期望得到一个可迭代对象作为参数,而不一定是数组。并且 map 的标准迭代会返回跟 map.entries() 一样的键/值对。因此,我们可以获得一个普通对象(plain object),其键/值对与 map 相同。

WeakMap 和 Map 区别

WeakMapMap的区别就在于Weak

JS 中垃圾回收程序对待“WeakMap”中键的方式

  • WeakMap相对于Map是一个不可枚举的对象,必须使用对象作为键值。
  • WeakMap 的键名引用的对象是弱引用^r