JavaScript中普通对象和Map对象的区别
在JavaScript中,普通对象({})
和 Map
对象都是用于存储键值对的数据结构,但是他们有一些区别。
1. 键的类型
普通对象: 对象的键必须是字符串或 Symbol
类型。其他类型的值(如数字、布尔值、对象等)会被强制转换为字符串。例如,1 和 “1” 在对象中是同一个键。
Map: Map
允许任何类型的值作为键,包括对象、函数、原始类型等。例如,1 和 “1” 在 Map 中是不同的键。
2. 键的顺序
普通对象: 在ES6之前,对象的键没有特定的顺序。但在现代JavaScript中,对象的字符串键按插入顺序排序,数字键按升序排序,Symbol 键的顺序未定义。
Map: Map 保留键的插入顺序,当你遍历 Map 时,键会按照插入的顺序被访问。
让我们考虑一个带有电话号码的对象:
let codes = {49: "Germany",41: "Switzerland",44: "Great Britain",// ..,1: "USA",
};for (let code in codes) {console.log(code); // 1, 41, 44, 49
}console.log(Object.keys(codes)); //[ '1', '41', '44', '49' ]
不论是in
操作符,还是Object.keys
,键的顺序是按照整数顺序排列的,同时Object.values
,也是对应的key
的顺序的
console.log(Object.keys(codes)); //[ '1', '41', '44', '49' ]
console.log(Object.values(codes)); //[ 'USA', 'Switzerland', 'Great Britain', 'Germany' ]
即 整数属性会被进行排序,其他属性则按照创建的顺序显示。
所谓整数属性 指的是一个可以在不做任何更改的情况下与一个整数进行相互转换的字符串。
非整数属性
如果属性名不是整数,那它们就按照创建时的顺序来排序,例如:
let user = {name: "John",surname: "Smith",
};
user.age = 25; // 增加一个// 非整数属性是按照创建的顺序来排列的
for (let prop in user) {console.log(prop); // name, surname, age
}
console.log(Object.keys(user)); //[ 'name', 'surname', 'age' ]
两者都有
既有整数属性也有非整数属性
let user = {name: "John",surname: "Smith",49: "Germany",41: "Switzerland",44: "Great Britain",1: "USA",
};
user.age = 25; // 增加一个
user["0"] = 23; // 增加一个// 既有整数属性也有非整数属性
// 1.整数属性会按照数字顺序排序,
// 2.非整数熟悉按照插入顺序
// 3.先输出的是整数属性
for (let prop in user) {console.log(prop); // 0,1,41,44,49,name, surname, age
}
console.log(Object.keys(user)); //[ '0', '1', '41', '44', '49', 'name', 'surname', 'age' ]
3.默认键
普通对象:普通对象继承自 Object.prototype
,因此默认带有一些预定义的键(如 toString
、hasOwnProperty
)。虽然这些键可以被覆盖,但在使用时需要注意可能的冲突。
const obj = { age: 20 };obj.__proto__.test = "haha";for (const k in obj) {console.log(k);/* age 自身的test 和原型对象的可枚举键*/}console.log(Object.keys(obj)); // ['age']console.log(Object.getPrototypeOf(obj));
注意:
for…in 循环只会迭代可枚举的非符号属性。从内置构造函数(如 Array 和 Object)创建的对象会从Array.prototype 和 Object.prototype 继承不可枚举属性,例如 Array 的 indexOf() 方法或Object 的 toString() 方法,它们在 for…in 循环中不会被访问到。
Map:Map 默认不包含任何键。它只包含显式存入的键值对。因此,Map 对象不会与任何原型链上的属性冲突。
const map = new Map();map.set("name", "zs"); //自有键map.set("age", 20); //自有键Object.getPrototypeOf(map).test = "haha"; //原型对象的键console.log(map.keys()); //MapIterator {'name', 'age'}
4.迭代性
普通对象:迭代对象的键需要使用 Object.keys()、Object.values()
或 Object.entries()
。对象本身并不是可迭代的(没有实现 Symbol.iterator
接口)。for...in
也可以遍历对象
for…in 不能直接遍历 Map 对象。它通常用于遍历普通对象的属性,而不是 Map 对象的键值对。
const map = new Map();map.set("name", "zs"); //自有键map.set("age", 20); //自有键for (const key in map) {console.log(key); //没有任何输出}
要遍历 Map 对象,map是可迭代的,使用for...of
或者
map.forEach() / map.keys() / map.values() / map.entries()
5.序列化
普通对象:对象可以使用 JSON.stringify()
进行序列化,结果是一个JSON字符串。
Map:Map 不能直接通过 JSON.stringify()
进行序列化,因为它不是一个普通的对象。如果需要序列化 Map,需要先将其转换为数组或对象。
普通对象的序列化
const obj = {name: "Alice",age: 30,city: "New York",};const jsonString = JSON.stringify(obj);console.log(jsonString); // {"name":"Alice","age":30,"city":"New York"}
Map 对象的序列化
Map 对象不能直接用 JSON.stringify()
进行序列化。如果你尝试这样做,结果会是一个空对象 {}。
const map = new Map();map.set("name", "Alice");map.set("age", 30);map.set("city", "New York");const jsonString = JSON.stringify(map);console.log(jsonString); // {}
为了正确序列化 Map
对象,你需要先将 Map
转换为可以被 JSON.stringify()
识别的格式,如数组或对象。
转换为普通对象
const map = new Map();
map.set("name", "Alice");
map.set("age", 30);
map.set("city", "New York");const mapObject = Object.fromEntries(map);
const jsonStringFromObject = JSON.stringify(mapObject);
console.log(jsonStringFromObject); // {"name":"Alice","age":30,"city":"New York"}
反序列化
对于 Map 对象,先将 JSON
字符串转换为数组或对象,再转换为 Map。
const map = new Map();
map.set("name", "Alice");
map.set("age", 30);
map.set("city", "New York");// 序列化
const mapObject = Object.fromEntries(map);
const jsonStringFromObject = JSON.stringify(mapObject);
console.log(jsonStringFromObject); // {"name":"Alice","age":30,"city":"New York"}// 反序列化
// 1.先将 JSON 字符串转换为数组或对象
const parsedObject = JSON.parse(jsonStringFromObject);
// 2.再转换为 Map
const parsedMapFromObject = new Map(Object.entries(parsedObject));
console.log(parsedMapFromObject.get("name")); // "Alice"
6.使用场景
普通对象:适用于管理少量数据,并且键是已知的、简单的字符串或符号的情况下。
Map:适用于需要灵活、动态键(特别是非字符串键),或者需要高效查找和操作大量键值对的场景。
相关文章:

JavaScript中普通对象和Map对象的区别
在JavaScript中,普通对象({})和 Map 对象都是用于存储键值对的数据结构,但是他们有一些区别。 1. 键的类型 普通对象: 对象的键必须是字符串或 Symbol 类型。其他类型的值(如数字、布尔值、对象等&#x…...

Liunx搭建Rustdesk远程桌面服务
1、环境准备 Linux:centos7.9 rustdesk server安装包 很多新服务器并没有 wget 和unzip 可以通过yum自行安装下,如果系统中有wget但不能使用,直接卸载重装即可。 yum install wget wget --no-check-certificate https://github.com/rust…...

antv X6--实现节点旁添加多个text标签
前言:接本专栏上篇文章,实现一个新需求,如有不懂的可先去看新手教程 需求描述:如何在节点旁添加多个标签,如下图所示: 实现该需求目前我只想到两种方法: 方法一:使用换行符将不同的…...
JAVA--多线程
Java中的多线程是指在同一个Java虚拟机(JVM)中并发执行多个线程的能力。线程是程序执行的最小单元,Java提供了丰富的API来创建和管理线程。以下是Java中实现多线程的一些关键概念和方法: Thread 类:Java提供了Thread类…...
ADB-DROM
# 读硬件信息 adb shell "cat /sys/block/mmcblk0/device/name" # MT6767/MT6768/MT6769/MT6762/MT6765/MT6761... # 频率档位 # 固定频率 adb shell "echo 0 > /sys/devices/platform/10012000.dvfsrc/helio-dvfsrc/dvfsrc_force_vcore_dvfs_opp" # …...
mysql 之 explain
1. 查看表的创建字段以及索引情况 show create table user_recommend; 2. 创建索引的原则:列的值比较离散 像性别字段,只有男,女 或者其他;expose字段,只有1分发,0不可分发。就不适宜在这种字段上添加索引…...

CentOS迁移案例 | 保障轨道交通安全、发挥基础设施效能,麒麟信安操作系统支撑某市轨道交通畅行无忧
为缓解城市交通拥堵难题,某市轨道交通公司计划新建一条贯穿城市关键区域、沿路设立20座站点的轨道交通线路,并基于麒麟信安操作系统构建轨道交通信号系统。 轨道交通信号系统是列车核心控制系统,负责列车运行的自动化控制,及对整…...
获取操作系统的信息(Go语言)
在 Go 语言中,你可以使用 runtime 和 os 包来查看操作系统的信息。以下是一些常见的操作系统信息获取方法: 1. 获取操作系统类型和架构信息 Go 的 runtime 包提供了基本的操作系统和架构信息: package mainimport ("fmt""r…...

【论文阅读】HuatuoGPT-II, One-stage Training for Medical Adaption of LLMs
总体概要 本文深入探讨了一款专为医疗领域设计的大规模语言模型——HuatuoGPT-II的创新、性能与应用。HuatuoGPT-II采用统一的单阶段训练流程,将传统的继续预训练和监督微调整合,有效解决了医疗数据的异质性问题,包括语言、体裁和格式差异&a…...
Excel表列序号
题目 给定一个Excel表格中的列名称,返回其相应的列序号。 例如, A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...示例 1: 输入: "A" 输出: 1示例 2: 输入: "AB" 输出: 28示例 3: 输入: "ZY&…...

IOS 03 纯代码封装自定义View控件
本节将通过纯代码进行封装自定义View控件,以常用的设置页的item为例,实现UI效果如下: 1、创建SettingView继承自UIView import UIKitclass SettingView: UIView {} 2、重写 init() 和 required init?(coder: NSCoder) 方法 纯代码创建Set…...

比较结构加法及其逆运算
在行列可自由变换的平面上有等式 13(3a11)2*4a14a22*4a32*4a44*4a122*4a14 3a11在平面上可能得到6个不同的4点结构,这6个结构的比例为2:1:2:2:4:2. 现在从右向左算,计…...

44.【C语言】指针(重难点)(G)
目录 19.字符指针变量 *定义 *简单说明 *如果是字符串 *像数组一样指定访问常量字符串的字符 *练习 20.数组指针变量 *定义 *格式 *例子 问题1 问题2 *利用指针打印 21.二维数组传参的本质 *回顾 往期推荐 19.字符指针变量 *定义 指向字符的指针变量,用于存储字符…...

746. 使用最小花费爬楼梯-dp3
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/min-cost-climbing-stairs/description/从左向右填dp表 class Solutio…...

MPU6050详细介绍
一、MPU6050介绍 MPU6050是由三个陀螺仪和三个加速度传感器组成的6轴运动处理组件 内部主要结构:陀螺仪、加速度计、数字运动处理器DMP(Digital Motion Processor) MPU6050有两个IIC接口,第一IIC接口可作为主接口给单片机传输数…...

【分享】Excel的3个隐藏功能
我们在制作Excel表格的时候,有时候会包含一些敏感信息,为了确保这些数据的安全性,Excel提供了隐藏功能来保护工作表,下面小编分享3个Excel常用的隐藏功能,一起来看看如何设置吧! 功能一:隐藏部分…...
Linux中的chown指令
chown(change owner)命令在 Linux 和其他类 Unix 系统中用于更改文件或目录的用户和/或组所有权。 基本用法 chown [选项] 用户名[:组名] 文件或目录 参数说明 用户名:指定新的文件或目录的所有者 组名:可选,指定新…...

UCOSIII内存管理机制详解
目录 前言 1. 内存管理概述 2. 内存区域(存储区)和内存块 3. 存储区控制块(OS_MEM) 4. 内存管理函数 5. 内存碎片问题 6. 注意事项 7.代码实现 7.1创建内存区域 7.2申请内存 7.3释放内存 前言 UCOSIII(即Mi…...

Android12 显示框架之Transaction----client端
目录:Android显示终极宝典 在前面的章节中,应用通过createSurface()在surfaceflinger中创建了一层layer,紧接着要做的事情就是对这个layer设置一些属性(或者叫状态),常设置的属性有位置、大小、z-order等等…...
在Windows上使用FRP搭建内网穿透:
FRP服务器端配置(公网服务器) 下载FRP: 访问FRP的GitHub发布页面:https://github.com/fatedier/frp/releases下载对应系统架构的frp_<version>_linux_amd64.tar.gz(如果你的服务器是Linux系统)或者f…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...

联邦学习带宽资源分配
带宽资源分配是指在网络中如何合理分配有限的带宽资源,以满足各个通信任务和用户的需求,尤其是在多用户共享带宽的情况下,如何确保各个设备或用户的通信需求得到高效且公平的满足。带宽是网络中的一个重要资源,通常指的是单位时间…...

GC1808:高性能音频ADC的卓越之选
在音频处理领域,高质量的音频模数转换器(ADC)是实现精准音频数字化的关键。GC1808,一款96kHz、24bit立体声音频ADC,以其卓越的性能和高性价比脱颖而出,成为众多音频设备制造商的理想选择。 GC1808集成了64倍…...