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

第8周验收


第二阶段前半总结(第7-8周:JS 地基)

周次主题
7数组方法 map/filter/reduce/find/some/every/includes
8解构 / 展开运算符 / async/await + fetch

这两周补的全是第一阶段”用过但没吃透”的 JS。现在回头看配色生成器的代码,应该每一行都讲得清”为什么这么写”了。