ES6之Map数据结构

ES6(ECMAScript 2015)引入了两种新的数据结构:Set和Map,它们为JavaScript开发者提供了更强大的数据处理能力。

Map(字典)

概念:

JavaScript 的对象(Object),本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

const	data	=	{};
const	element	=	document.getElementById('myDiv');
data[element]	=	'metadata';
data['[object	HTMLDivElement]']	//	"metadata"

上面代码原意是将一个DOM 节点作为对象data的键,但是由于对象只接受字符串作为键名,所以element被自动转为字符串[object HTMLDivElement] 。

为了解决这个问题,ES6提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

也就是说,Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的 Hash结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

Map是一种键值对集合,类似于对象,但是键的范围不限于字符串,可以是任何值(包括对象)。Map更适用于需要使用非字符串作为键,或者需要更高效的键值对操作的场景。
const	m	=	new	Map();
const	o	=	{p:	'Hello	World'};

m.set(o,	'content')
m.get(o)	//	"content"
m.has(o)	//	true
m.delete(o)	//	true
m.has(o)	//	false

特点:

  • 键可以是任何类型。
  • 可以通过键直接获取值,提高查找效率。
  • 支持更多的集合操作,如大小查询、键值对的增删等。

如果Map的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map将其视为一个键,比如0 和布尔值true和字符串-0就是一个键,true则是两个不同的键。

另外,undefined 和null也是两个不同的键。

虽然NaN不严格相等于自身,但Map将其视为同一个键。

let	map	=	new	Map();

map.set(-0,	123);
map.get(+0)	//	123

map.set(true,	1);
map.set('true',	2);
map.get(true)	//	1

map.set(undefined,	3);
map.set(null,	4);
map.get(undefined)	//	3

map.set(NaN,	123);
map.get(NaN)	//	123

实例的属性和操作方法

size属性

size 属性返回 Map 结构的成员总数。

const map = new Map();
map.set('foo', true);
map.set('bar', false);

map.size // 2
set(key, value)

set 方法设置键名 key 对应的键值为 value ,然后返回整个 Map 结构。如果 key 已经有值,则键值会被更新,否则就新生成该键。

const m = new Map();

m.set('edition', 6) // 键是字符串
m.set(262,'standard') // 键是数值
m.set(undefined,'nah') // 键是 undefined

set 方法返回的是当前的 Map 对象,因此可以采用链式写法。

let map = new Map()
    .set(1,'a')
    .set(2,'b')
    .set(3,'c');
get(key)

get 方法读取 key 对应的键值,如果找不到 key ,返回 undefined 。

const m = new Map();
const hello = function() {console.log('hello');};

m.set(hello,'Hello ES6!') // 键是函数
m.get(hello) // Hello ES6!
has(key)

has 方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

const m = new Map();
m.set('edition', 6);
m.set(262,'standard');
m.set(undefined,'nah');

m.has('edition') // true
m.has('years') // false
m.has(262) // true
m.has(undefined) // true
delete(key)

delete 方法删除某个键,返回 true 。如果删除失败,返回 false 。

const m = new Map();
m.set(undefined,'nah');
m.has(undefined) // true
m.delete(undefined)
m.has(undefined) // false
clear()

clear 方法清除所有成员,没有返回值。

let map = new Map();

map.set('foo', true);
map.set('bar', false);
map.size // 2

map.clear()
map.size // 0
遍历方法

Map 结构原生提供三个遍历器生成函数和一个遍历方法。

  • keys() :返回键名的遍历器。
  • values() :返回键值的遍历器。
  • entries() :返回所有成员的遍历器。
  • forEach() :遍历 Map 的所有成员。

需要特别注意的是,Map 的遍历顺序就是插入顺序。

const map = new Map([
    ['F','no'],
    ['T','yes'],
]);

for (let key of map.keys()) {
    console.log(key);
}
// "F"
// "T"

for (let value of map.values()) {
    console.log(value);
}
// "no"
// "yes"

for (let item of map.entries()) {
    console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
    console.log(key, value);
}
// "F" "no"
// "T" "yes"

// 等同于使用map.entries()
for (let [key, value] of map) {
    console.log(key, value);
}
// "F" "no"
// "T" "yes"
Map 结构转为数组结构,比较快速的方法是使用扩展运算符( … )。
const map = new Map([
    [1,'one'],
    [2,'two'],
    [3,'three'],
]);

[...map.keys()]
// [1, 2, 3]

[...map.values()]
// ['one','two','three']

[...map.entries()]
// [[1,'one'], [2,'two'], [3,'three']]

[...map]
// [[1,'one'], [2,'two'], [3,'three']] 
结合数组的 map 方法、 filter 方法,可以实现 Map 的遍历和过滤

(Map 本身没有 map 和 filter 方法)。

const map0 = new Map()
.set(1,'a')
.set(2,'b')
.set(3,'c');

const map1 = new Map(
    [...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}

const map2 = new Map(
    [...map0].map(([k, v]) => [k * 2,'_' + v])
);
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}
Map forEach 方法,与数组的 forEach 方法类似,也可以实现遍历。
map.forEach(function(value, key, map) {
    console.log("Key: %s, Value: %s", key, value);
});

forEach 方法还可以接受第二个参数,用来绑定 this 。

const reporter = {
    report: function(key, value) {
        console.log("Key: %s, Value: %s", key, value);
    }
};

map.forEach(function(value, key, map) {
    this.report(key, value);
}, reporter);

上面代码中, forEach 方法的回调函数的 this ,就指向 reporter 。

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

在ECMAScript 6 (ES6) 中,Map 是一种新的集合类型,它允许你以键值对的形式存储数据。Map 与其他数据结构之间的互相转换是常见的操作,以下是一些基本的转换方法:

Map 转换为其他数据结构
Map 转为数组 (Array): 扩展运算符 ...Array.from()

使用扩展运算符 (...) 或 Array.from() 方法可以轻松地将 Map 转换为数组。

let myMap = new Map([['key1', 'value1'], ['key2', 'value2']]);
let arrayFromMap = [...myMap];
// 或者
let arrayFromMap = Array.from(myMap);
Map 转为 Object: Object.fromEntries

如果你想将 Map 转换为普通的 JavaScript 对象,可以通过 Object.fromEntries() 方法来实现。

let myMap = new Map([['key1', 'value1'], ['key2', 'value2']]);
let objectFromMap = Object.fromEntries(myMap);
Map 转为 JSON 字符串:

虽然 Map 不能直接转换为 JSON,但你可以先将其转换为数组或对象,然后再转换为 JSON。

let myMap = new Map([['key1', 'value1'], ['key2', 'value2']]);
let jsonArrayFromMap = JSON.stringify([...myMap]);
// 或转换为对象后序列化
let jsonObjectFromMap = JSON.stringify(Object.fromEntries(myMap));
数组转为 Map:

可以直接将一个二维数组传给 Map 构造函数来创建一个新的 Map 实例。

let myArray = [['key1', 'value1'], ['key2', 'value2']];
let mapFromArray = new Map(myArray);
Object 转为 Map: Object.entries()

使用 Object.entries() 获取对象的所有可枚举属性的键值对数组,然后传递给 Map 构造函数。

let myObject = { key1: 'value1', key2: 'value2' };
let mapFromObject = new Map(Object.entries(myObject));
JSON 字符串转为 Map:

首先将 JSON 字符串解析为数组或对象,然后再转换为 Map

let jsonString = '{"key1":"value1","key2":"value2"}';
let parsedObject = JSON.parse(jsonString);
let mapFromJson = new Map(Object.entries(parsedObject));

这些转换方法可以帮助你在不同数据结构间灵活地操作数据,以满足不同的编程需求。

  • 44
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端布道人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值