一文吃透 JavaScript 中 Object 和 Map 的区别

本文详细对比了JavaScript中的对象和Map数据结构,包括构造方式、键的类型、键的顺序、接口差异、JSON支持及性能特点。Map提供了更灵活的键管理和更好的访问接口,适合频繁增删操作,而对象更适合静态键值对。
摘要由CSDN通过智能技术生成

本文由技术评估与在线 Coding 面试平台 ShowMeBug 技术团队翻译。

在 JavaScript 中,ObjectMap 都是键值对的动态集合。虽然两者的定义差不多,但区别也不少。下面跟我一起来看看吧~

1.构造方式不同

在 JavaScript 中创建 Object 最简单的方法是通过字面量。

const smbObj = {
  1: 'ShowMeBug',
  2: 'ShowMeMoney'  
};

Map 则是通过内置构造函数 Map 创建。

const smbMap = new Map([
  [1, 'ShowMeBug'],
  [2, 'ShowMeMoney']
]);

接下来,我会用“对象”或“对象映射”来表示通过字面量创建的键值集合,用“映射”来表示通过内置构造函数 Map 创建的映射。

2.对象中的键是字符串,映射中的键可以是任意类型

Object 是键值对的集合,但键只能是字符串。而 Map 的键可以是任意类型。

比如,如果用数字作 Object 的键,则该数字将转换为字符串。

因为键已经被转换成字符串,所以无论我们是获取数字 1 还是字符串 '1' 的值时,得到的结果都一样。

console.log(smbObj[1]);
//'ShowMeBug'
console.log(smbObj['1']);
//'ShowMeBug'

Map 的键可以为任意类型,数字 1 的键和字符串 '1' 的键并不一样。

console.log(smbMap[1]);
//'ShowMeBug'
console.log(smbMap['1']);
//undefined

无论是对象还是映射,键都是唯一的。对象中不能有两个相同键的属性,映射中也不能有两个相同键的条目。

3.对象会从原型中继承多余的键

另一个区别是,使用字面量创建的 Object 会继承一组来自 Object.prototype 的键值对。

打印 Object.prototype,你会发现它还有 hasOwnPropertyisPrototypeOftoLocaleStringtoString 等属性。

console.log(Object.prototype);

通过字面量创建的 Object 也会有这些属性。空对象 {} 并不是真的为空。可以看看下列代码。

const socalledEmptyObject = {};
console.log(socalledEmptyObject['toString']);
//ƒ toString() { [native code] }

我们创建了一个所谓的“空”对象,却能够访问其上的 toString 键。创建对象映射最好是用 Object.create(null) 来做。

const emptyObject = Object.create(null);
console.log(emptyObject['toString']);
//undefined

Object.create(null) 能构建出没有原型的对象。

4.Map 会保留键的顺序,对象不会

键值对的原始顺序会在 Map 中得到保留,而在对象中则不会。

const smbObj = {
  2: 'ShowMeMoney',
  1: 'ShowMeBug'  
};

const keys = Object.keys(smbObj);
console.log(keys);
//["1", "2"]

const keyValuePairs = Object.entries(smbObj);
console.log(keyValuePairs);
//["1", "ShowMeBug"]
//["2", "ShowMeMoney"]

在这里插入图片描述

注意,创建对象时,键 2 出现在键 1 之前。但在检索所有键时,21 后面。

下面用 Map 构造函数创建一个类似的集合。这一次键的初始顺序得到了保留。

const smbMap = new Map([
  [2, 'ShowMeMoney'],
  [1, 'ShowMeBug']
]);

const keys = smbMap.keys();
console.log(keys);
//MapIterator {2, 1}

const keyValuePairs = smbMap.entries();
console.log(keyValuePairs);
//MapIterator {2 => "ShowMeMoney", 1 => "ShowMeBug"}

5.Map 提供了更好的接口来访问键值对

获取

访问对象上的属性可以通过点运算符或方括号运算符来完成。在本文的例子中,因为键用的是数字,所以只能用方括号运算符。

smbObj[1];
//'ShowMeBug'

而在 Map 上,则需要用 get(key) 方法来获取值。

smbMap.get(1);
//'ShowMeBug'

检查键是否存在

Map 可以用 has(key) 来检查键是否存在。

smbMap.has(1);
//true
smbMap.get(3);
//false

对象则可以用 hasOwnProperty(key) 方法。

smbObj.hasOwnProperty(1);
//true
smbObj.hasOwnProperty(3);
//false

添加键值对

set(key, value)Map 中添加新的键值对。

smbMap.set(3, 'ShowMeFeature'); 
//{1=>'ShowMeBug', 2=>'ShowMeMoney', 3=>'ShowMeFeature'}

而对于对象,我们使用方括号或点运算符来添加新的键值对。

smbObj[3] = 'ShowMeFeature';
//{ 1: 'ShowMeBug', 2: 'ShowMeMoney', 3: 'ShowMeFeature'};

删除键值对

Map 可以通过 delete(key) 方法来删除键值对。

smbMap.delete(1);

对象则可以用 delete 操作符。

delete smbObj[1];

读取键值对数量

Mapsize 属性来记录内部的键值对数量。

console.log(smbMap.size);

对象没有获取键值对数量的特定方法。我们需要使用像 Object.keys() 这样的外部帮助函数。

const size = Object.keys(smbObj).length;
console.log(size);

6.对象需要帮助函数来访问键值对

我们可以用 forEach 方法遍历 Map 中的条目。

const smbMap = new Map([
  [1, 'ShowMeBug'],
  [2, 'ShowMeMoney']
]);



smbMap.forEach((value, key)=>{
   console.log(`${key} - ${value}`)
});
//1 - ShowMeBug
//2 - ShowMeMoney

至于对象,我们可以用 Object.entries() 辅助函数进行迭代。

Object.entries() 会以 [key, value] 键值对数组的形式返回对象的所有属性。一旦拿到这一数组,就能用 forEach 这样的数组方法了。

const smbObj = {
  1: 'ShowMeBug',
  2: 'ShowMeMoney'  
};

Object
  .entries(smbObj)
  .forEach(([key, value])=>{
    console.log(`${key} - ${value}`)
  });
//1 - ShowMeBug
//2 - ShowMeMoney

7.JSON支持对象,但不支持 Map

const smbObj = {
  1: 'ShowMeBug',
  2: 'ShowMeMoney'  
};

const json = JSON.stringify(smbObj);
console.log(json);
//{"1":"ShowMeBug","2":"ShowMeMoney"}

JSON 不支持 Map,序列化的结果是一个空对象。

const smbMap = new Map([
  [1, 'ShowMeBug'],
  [2, 'ShowMeMoney']
]);

const json = JSON.stringify(smbMap);
console.log(json);
//{}

总结

JavaScript 中的对象在其他语言中被称为哈希映射。访问映射对象中的键所需时间为 O(1),这意味着获取键所需的时间为常量,而不管对象映射中的数据量如何。

不管这些键值集合是用 Map 构造函数还是对象字面量创建的,它们都主要用于快速搜索数据,键的访问时间都是 O(1),检索键也不需要扫描所有数据。

Map 为管理键值对提供了更好的接口。在需要添加和删除条目的场景中,Map 是更好的选择。而如果创建键值集合只是用来搜索键时,对象就够了。

原文链接:7 Differences between Objects and Maps in JavaScript

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统是计算机系统的核心组成部分,负责管理和协调计算机硬件和软件资源,提供程序运行环境。在CSDN上有很多关于操作系统的专题文章,以下将从操作系统的基本概念、功能和常见类型等方面简要介绍一下。 首先是操作系统的基本概念。操作系统是一种系统软件,它是计算机硬件和应用软件之间的桥梁,提供给应用程序一系列的服务和资源,同时负责调度和管理系统资源。它为用户屏蔽了底层的硬件差异,提供了一个统一的、易于使用的界面。 操作系统主要有四个基本功能。首先是处理器管理,负责将处理器分配给系统的各个进程,并进行进程切换,实现多道程序并发执行。其次是内存管理,管理计算机的内存资源,包括分配、回收和保护等操作。再次是文件管理,负责管理文件的存储、命名和保护等操作,提供了文件操作的接口。最后是设备管理,负责管理计算机的各种设备,包括输入输出设备和存储设备等。 常见的操作系统有多种类型。最主流的是Windows、Linux和Mac OS等桌面操作系统。此外还有服务器操作系统,如Windows Server和Linux等,用于管理和部署服务器。还有嵌入式操作系统,如Android和iOS等,用于移动设备和物联网设备。操作系统也有实时操作系统,用于需要实时控制和响应的系统,如工控系统和航空航天系统等。 总之,操作系统是计算机系统不可或缺的重要组成部分,通过CSDN上的相关文章,我们可以更深入了解操作系统的基本概念、功能和不同类型。这些知识对于理解计算机系统的工作原理和提升编程能力都有着重要意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值