JS 第8周笔记-解构 + 展开运算符 + async&await
路线图阶段:第二阶段(现代 JavaScript 补全)第8周 性质:夯实第一阶段用过但没系统学的三块 JS 地基 三块:解构(destructuring)、展开运算符(spread)、async/await + fetch
一、解构(Destructuring):从数组/对象拆值进变量
你早就在用:
const [count, setCount] = useState(0); // 数组解构
function SearchBar({ query, onQueryChange }) // 对象解构
photos.map(([role, color]) => ...) // 数组解构
对象解构:用 {},按”名字”匹配
const user = { name: "Kevin", age: 31 };
const { name, age } = user; // 变量名必须和 key 一致
const { age, name } = user; // 顺序无所谓,靠名字
数组解构:用 [],按”位置”匹配
const arr = ["red", "green", "blue"];
const [first, second] = arr; // 名字随便起,只看位置
这就是 useState 能随便命名的原因:
const [count, setCount] = useState(0);
// ↑ 自起名,因为数组解构只看位置(第0位=值,第1位=改值函数)
跳过占位(数组)
const [, , blue] = colors; // 用逗号跳过前两个位置,只取第三个
进阶用法
1. 默认值(key 不存在时兜底)
const { theme, fontSize = 16 } = settings; // 没有 fontSize → 用 16
// React 常用:function Button({ label, size = "medium" }) {}
2. 重命名(换变量名 / 避免冲突)
const { name: userName } = user; // 拆 name,存进 userName 变量
// 原key: 新名字
3. 嵌套解构(对象里的对象)
const { author: { name } } = photo; // 进入 author,再拆 name
// 等于 photo.author.name,但层级深了可读性下降,适度用
二、展开运算符(Spread)...:把数组/对象”摊开”
你早就在用:
setList([...list, newItem]); // Todo 添加
{ ...item, finish: !item.finish } // Todo 标记完成
数组展开
const newList = [...list, 4]; // 复制 list 元素 + 加 4 → 全新数组
const merged = [...a, ...b]; // 合并两数组
关键:这是创建新数组,不是改原数组。这正是 React 不可变更新的基础 —— 绝不 list.push(),要用 … 造新的。
对象展开
const updated = { ...user, city: "Osaka" }; // 复制 + 加字段
const aged = { ...user, age: 32 }; // 复制 + 覆盖字段
机制:后面的覆盖前面的。 { …user, age: 32 } 先摊开(含 age:31),再写 age:32 覆盖。 这就是更新对象 state 的标准姿势:改一个字段、保留其余。
⚠️ 易混:… 在不同位置含义相反
// 构造/取值时 → 摊开(spread)
const newList = [...list, 4];
// 函数参数/解构时 → 收集(rest)
function sum(...nums) { } // 多个参数收集成数组 nums
const [first, ...others] = arr; // 剩下的收集成 others 数组
构造时”摊开”,接收时”收集”。
三、async/await + fetch
核心问题:异步
网络请求(fetch)发出去不会立刻有结果,要等服务器响应。JS 不傻等,继续往下跑,结果回来再处理。
处理”等结果”有两套语法:.then() 链 和 async/await(现代主流)。
三个核心规则
规则1:await 只能写在 async 函数里
async function loadData() { // 必须标 async
const res = await fetch(...); // 才能用 await
}
await = “在这里等这个 Promise 出结果,拿到再往下走”。
规则2:await 后面跟”返回 Promise 的东西”
const res = await fetch(url); // fetch 返回 Promise
const data = await res.json(); // res.json() 也返回 Promise,也要 await!
⚠️ 漏掉第二个 await,data 拿到的是 Promise,不是真数据。
规则3:错误处理用 try/catch,且 await 不能漏
async function loadData() {
try {
const res = await fetch(url);
const data = await res.json();
// 用 data...
} catch (error) {
console.log("出错:", error);
}
}
⚠️ try/catch 要对异步生效,await 必须在场(第6周复制 bug 的教训:async 标了但漏 await,catch 抓不到将来的错误)。
await 会”暂停”函数(理解关键)
async function loadData() {
console.log("1. 开始");
const res = await fetch(url); // ⏸ 暂停,等 fetch 完成
console.log("2. 拿到响应"); // 等上面完成才执行
const data = await res.json(); // ⏸ 再暂停,等解析
console.log("3. 数据就绪");
}
// 输出顺序一定是 1 → 2 → 3
- 好处:异步代码读起来像同步代码,从上往下顺着读,不用陷进 .then() 嵌套。
- 函数内部暂停,但函数外面不卡住:JS 先去干别的,Promise 好了再回来。所以页面不卡死。
第8周验收
- 懂对象解构(按名字)vs 数组解构(按位置),会跳过占位
- 会用解构默认值 / 重命名 / 嵌套
- 懂 spread 摊开数组/对象,“后者覆盖前者”,理解不可变更新
- 分清 … 摊开(构造时)vs 收集(接收时)
- 掌握 async/await 三规则 + await 暂停机制
第二阶段前半总结(第7-8周:JS 地基)
| 周次 | 主题 |
|---|---|
| 7 | 数组方法 map/filter/reduce/find/some/every/includes |
| 8 | 解构 / 展开运算符 / async/await + fetch |
这两周补的全是第一阶段”用过但没吃透”的 JS。现在回头看配色生成器的代码,应该每一行都讲得清”为什么这么写”了。