大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
对象与 JSON
这一课你将能做到
- 用对象字面量描述「一个用户 / 一门课」,并读写属性
- 会用可选链
?.与解构,避免对null/undefined取属性报错 - 说出 JSON 是什么,以及
JSON.stringify/JSON.parse干什么
为什么要学
现实事物有多个字段:课程有标题、是否完成、时长。
对象把这些字段放在一个值里。前后端传数据常用 JSON(一种文本格式,长得像 JS 对象)。
学完数组你会处理「一列」;学完对象你会处理「一条记录」。
两者组合——Array of Object——就是绝大多数前端列表的数据形状。
先建立图像
const lesson = {
title: "HTML",
done: false,
minutes: 30,
};
// 像一张表格行:字段名 → 值
变量 lesson ──●──► 堆里的对象 { title, done, minutes }
(装的是引用/地址;赋值给别人可能共享同一份)
| 概念 | 人话 |
|---|---|
| 对象 | 一组命名字段打成一个值 |
| 属性 | 字段名与值的一对 |
| JSON | 跨系统传数据的文本格式 |
| 浅拷贝 | 只复印第一层,内层仍可能共享 |
跟着做
步骤 1:读写与新增属性
const user = { name: "ada", score: 10 };
console.log(user.name); // 点号读
console.log(user["score"]); // 方括号读(键动态时有用)
user.score = 12; // 改
user.city = "天津"; // 新增字段
console.log(user);
你应在控制台看到带 city 的对象。const 并不阻止改属性。
步骤 2:解构与剩余属性
const lesson = { title: "JS", done: true, minutes: 40 };
const { title, done } = lesson; // 一次性取出
console.log(title, done);
const { minutes, ...rest } = lesson;
console.log(minutes, rest); // 40 与 { title, done }
解构让参数和返回值更干净;后面函数「收一个配置对象」时很常见。
步骤 3:浅拷贝坑(重要)
const a = { profile: { city: "天津" } };
const b = { ...a }; // 展开运算:浅拷贝
b.profile.city = "北京";
console.log(a.profile.city); // "北京" —— 内层还是同一份!
// 第一层换绑则互不影响:
const c = { ...a, title: "副本" };
c.title = "改了";
console.log(a.title); // undefined(a 本来就没有 title)
人话:{...a} 只复制第一层。内层对象仍共享。改嵌套字段要小心。
步骤 4:可选链与空值合并
const data = { user: null };
// console.log(data.user.name); // TypeError
console.log(data.user?.name); // undefined,不报错
console.log(data.user?.profile?.city ?? "未知城市");
?.:左边是 null/undefined 就短路成 undefined。
再配合 ?? 给展示层默认值。
步骤 5:JSON 序列化与解析
const obj = { title: "JS", done: true };
const text = JSON.stringify(obj); // 对象 → 字符串(方便传输/存储)
console.log(text); // {"title":"JS","done":true}
const back = JSON.parse(text); // 字符串 → 对象
console.log(back.title);
// 美化打印(第二个参数 null,第三个缩进空格数)
console.log(JSON.stringify(obj, null, 2));
JSON 不能完美表示函数;Date 等也会变成字符串。它是数据交换格式,不是完整 JS。
步骤 6:页面展示一门课对象
保存为 js-objects.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>对象与 JSON</title>
</head>
<body>
<pre id="out"></pre>
<button type="button" id="toggle">切换完成状态</button>
<script>
const lesson = { title: "对象与 JSON", done: false, minutes: 30 };
function render() {
// 用 JSON 美化展示当前数据(调试利器)
document.getElementById("out").textContent =
JSON.stringify(lesson, null, 2);
}
render();
document.getElementById("toggle").addEventListener("click", function () {
lesson.done = !lesson.done; // 改对象字段
render();
});
</script>
</body>
</html>
点击按钮:done 应在 true/false 间切换,<pre> 里的 JSON 跟着变。
讲清楚要点
- 因为事物有多字段,所以用对象而不是一堆散落变量。
- 因为属性名通常是字符串,所以可用点号或方括号;动态键必须用方括号。
- 因为变量存的是引用,所以赋值/浅拷贝可能共享内层对象。
- 因为接口数据可能缺字段,所以用
?.和??做安全读取与默认值。 - 因为网络只传文本,所以用
JSON.stringify/JSON.parse做对象 ↔ 字符串。 - 因为JSON 键必须双引号且不支持函数,所以别手写拼接 JSON,也别指望它保存行为。
你可能会懵的地方
-
数组也是对象?
某种意义上是,但请用数组方法处理列表,别把数组当普通字典乱加命名属性。 -
const对象为何能改属性?
const禁止换绑,不禁止改对象内部。 -
深拷贝怎么办?
简单 JSON 数据可用structuredClone(o)(现代浏览器)或有局限的JSON.parse(JSON.stringify(o))。
初学先避免共享嵌套引用,比急着深拷贝更重要。 -
对象键的顺序?
大多数情况下字符串键按插入顺序枚举,但业务上别依赖奇技淫巧;需要严格顺序用数组。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 用对象当乱序列表容器 | 难遍历、难排序 | 列表用数组 |
| 忽略浅拷贝 | 改 B 动 A | 明白共享引用;必要时深拷贝 |
| 手动拼 JSON 字符串 | 引号/逗号易错 | JSON.stringify |
| 对可能为空的链一路点号 | TypeError | 可选链 ?. |
alert(obj) 看对象 | 看到无意义内容 | JSON.stringify(obj, null, 2) |
自测三问
- 对象和数组各适合描述什么?二者如何组合?
- 浅拷贝为什么改嵌套属性会影响原对象?
stringify/parse一对操作为什么在前后端交互里常见?
小结一句话
对象描述多字段事物;注意引用与浅拷贝;用可选链安全读字段;JSON 负责把对象变成可传输文本再解析回来。