我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaScript 中有了Object 为什么还需要 Map 呢

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaScript 中有了Object 为什么还需要 Map 呢

一、别把对象当 Map

1、可能通过原型链访问到未定义的属性

假设现有场景,开发一个网站,需要提供日语、汉语、韩语三种语言,我们可以定义一个字典去管理。


const dictionary = {
    'ja': {
        'Ninjas for hire': '忍者を雇う',
    },
    'zh': {
        'Ninjas for hire': '忍者出租',
    },
    'ko': {
        'Ninjas for hire': '고용 닌자',
    }
}

console.log(dictionary.ja['Ninjas for hire']) // 忍者を雇う
console.log(dictionary.zh['Ninjas for hire']) // 忍者出租
console.log(dictionary.ko['Ninjas for hire']) // 고용 닌자

这样我们就把不同语言的字典管理起来了。但是,当我们试图访问 constroctor 属性,问题就出现了。


console.log(dictionary.ko['constructor']) // ƒ Object() { [native code] }

对于不存在的属性,我们期望得到 undefined,结果却通过原型链访问到了未定义的属性,原型对象的 constructor 属性,指向构造函数。

此处有一个解决办法是把原型设置为 null


Object.setPrototypeOf(dictionary.ko, null)
console.log(dictionary.ko['constructor']) // undefined

2、对象的 Key 只能是字符串

假设需要将对象的 key 映射为 html 节点。我们写如下代码:




const firstElement = document.getElementById('firstElement')
const secondElement = document.getElementById('secondElement')

const map = {}

map[firstElement] = {
    data: 'firstElement'
}
map[secondElement] = {
    data: 'secondElement'
}

console.log(map[firstElement].data)     // secondElement
console.log(map[secondElement].data)    // secondElement

第一个元素的数据被覆盖了,原因是对象中的 key 只能是字符串类型,当我们没有使用字符串类型时,它会隐式调用 toString() 函数进行转换。于是两个 html 元素都被转为字符串 [object HTMLDivElement]

对象的键也可以为 Symbol,不过在 for..in 遍历和 Object.keys() 以及用 JSON.stringify() 进行序列化的时候,都会忽略为 Symbol 的键。

二、使用 Map

1、Map 常用操作

Map 可以使用任何 JavaScript 数据类型作为键


function People(name) {
    this.name = name
}
const zhangsan = new People('zhangsan')
const xiaoming = new People('xiaoming')
const lihua = new People('lihua')
// 创建 Map
const map = new Map()
// 创建 Map 并进行初始化 将二维键值对数组转换成一个Map对象
const map1 = new Map([
    ['key1', 'val1'],
    ['key2', 'val2'],
])
// 将 Map 转为二维数组
console.log(Array.from(map1)) // [ [ 'key1', 'val1' ], [ 'key2', 'val2' ] ]
// 设置键值映射关系
map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })
// 根据 key 获取对应值
console.log(map.get(zhangsan)) // { region: 'HB' }
console.log(map.get(xiaoming)) // { region: 'HN' }
// 获取不存在的 key 得到 undefined
console.log(map.get(lihua))     // undefined
// 通过 has 函数判断指定 key 是否存在
console.log(map.has(lihua))     // false
console.log(map.has(xiaoming))  // true
// map存储映射个数
console.log(map.size)           // 2
// delete 删除 key
map.delete(xiaoming)
console.log(map.has(xiaoming))  // false
console.log(map.size)           // 1
// clear 清空 map
map.clear()
console.log(map.size)           // 0

2、遍历 Map

Map 可以确保遍历的顺序和插入的顺序一致


const zhangsan = { name: 'zhangsan' }
const xiaoming = { name: 'xiaoming' }
const map = new Map()
map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })
// 每个键值对返回的是 [key, value] 的数组
for (let item of map) { // = for (let item of map.entries()) {
    console.log(item)
    // [ { name: 'zhangsan' }, { region: 'HB' } ]
    // [ { name: 'xiaoming' }, { region: 'HN' } ]
}
// 遍历 key
for (let key of map.keys()) {
    console.log(key)
    // { name: 'zhangsan' }
    // { name: 'xiaoming' }
}
// 遍历 value
for (let key of map.values()) {
    console.log(key)
    // { region: 'HB' }
    // { region: 'HN' }
}
// 使用 forEach() 方法迭代 Map
map.forEach(function(value, key) {
    console.log(key, value)
    // { name: 'zhangsan' } { region: 'HB' }
    // { name: 'xiaoming' } { region: 'HN' }
})

3、Map 中判断 key 相等

Map 内部使用 SameValueZero 比较操作。

关于SameValue SameValueZero

SameValue (Object.is()) 和严格相等(===)相比,对于 NaN 和 +0,-0 的处理不同


Object.is(NaN, NaN) // true
Object.is(0, -0) // false

SameValueZero SameValue 的区别主要在于 0 与 -0 是否相等。


map.set(NaN, 0)
map.set(0, 0)
console.log(map.has(NaN))   // true
console.log(map.has(-0))    // true

4、复制或合并 Map

Map 能像数组一样被复制


let original = new Map([
    [1, {}]
])
let clone = new Map(original) // 克隆 Map

console.log(clone.get(1)); // {}
console.log(original === clone) // false
console.log(original.get(1) === clone.get(1)) // true

多个 Map 合并


let first = new Map([
    [1, 'one'],
    [2, 'two'],
    [3, 'three'],
]);
let second = new Map([
    [1, 'uno'],
    [2, 'dos']
]);
// 合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的。
// 展开运算符本质上是将 Map 对象转换成数组。
let merged = new Map([...first, ...second]);

console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three

5、Map 序列化

Map 无法被序列化,如果试图用 JSON.stringify 获得 Map 的 JSON 的话,只会得到 "{}"。

由于 Map 的键可以是任意数据类型,而 JSON 仅允许将字符串作为键,所以一般情况下无法将 Map 转为 JSON。

不过可以通过下面的方式去尝试序列化一个 Map:


// 初始化 Map(1) {"key1" => "val1"}
const originMap = new Map([['key1', 'val1']])
// 序列化 "[[\"key1\",\"val1\"]]"
const mapStr = JSON.stringify(Array.from(originMap.entries())) 
// 反序列化 Map(1) {"key1" => "val1"}
const cloneMap = new Map(JSON.parse(mapStr))

三、Map 和 Object 的性能差异

内存占用

不同浏览器的情况不同,但给定固定大小的内存,Map 大约可以比 Object 多存储 50% 的键/值对。

插入性能

Map 略快,如果涉及大量操作,建议使用 Map

查找速度

性能差异极小,但如果只包含少量键/值对,则 Object 有时候速度更快。Object 作为数组使用时浏览器会进行优化。如果涉及大量查找操作,选择 Object 会更好一些。

删除性能

如果代码涉及大量的删除操作,建议选择 Map

到此这篇关于JavaScript 中有了Object 为什么还需要 Map 呢的文章就介绍到这了,更多相关JavaScript  Map 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaScript 中有了Object 为什么还需要 Map 呢

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

为什么linux中不需要磁盘碎片整理呢

这篇文章将为大家详细讲解有关为什么linux中不需要磁盘碎片整理呢,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。绝大多数的电脑用户都是在使用windows系统,我们都知道当电脑用起来很慢的时候,其中的一个
2023-06-13

云服务器就是不用买电脑了嘛为什么还要收费呢

云服务器是一种提供在线计算服务的设备,它通常需要付费购买。与其他计算设备类似,云服务器的成本通常包括带宽、存储和服务器硬件设备等方面的费用,而不仅仅是购买价格。尽管云服务器提供了更多的灵活性和便利性,但它们的价格也相对较高,而且通常需要付费使用,例如按年付费,以支持更长时间的使用。此外,许多云服务器还支持多用户或多租户功能,因此用户需要与其他用户共享计算资源和带宽,可能产生额外的成本。因此,尽管云服务器是一个...
2023-10-26

大企业需要安装SSL证书能理解,为什么中小企业也需要呢?

大企业需要安装SSL证书能理解,为什么中小企业也需要呢?在今天的互联网环境下,网络安全的重要性日益凸显。SSL证书是为网站提供安全保障的重要手段之一,它对于大企业的意义与价值已经被大多数人理解并接受。然而,其实对于中小企业来说,SSL证书同样重要性。下面将介绍,为什么中小企业也需要安装SSL证书。
大企业需要安装SSL证书能理解,为什么中小企业也需要呢?
2024-02-29

编程热搜

目录