0Pricing
JavaScript Academy · 课时

避免修改原数据

使用副本,而不是直接修改数据。

避免修改原数据 是 CoddyKit 上的免费 JavaScript Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 JavaScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 JavaScript Academy 课程共包含 4 节课。

为什么避免修改

修改共享数据会导致难以追踪的错误:一个位置的变化可能让其他位置的代码感到意外。函数式风格倾向于创建新值,而不是修改已有值(不可变性)。

const original = [1, 2, 3];
const copy = [...original, 4];
console.log(original); // [1, 2, 3]
console.log(copy);     // [1, 2, 3, 4]

使用展开复制数组

展开运算符 ... 会创建数组的浅拷贝,让您可以添加元素而不触碰源数组。

const nums = [1, 2, 3];
const more = [...nums, 4, 5];
console.log(more); // [1, 2, 3, 4, 5]
console.log(nums); // [1, 2, 3]

使用展开复制对象

展开运算符同样适用于对象,可以生成一个包含相同属性以及任意覆盖值的新对象。

const user = { name: "Ada", age: 36 };
const older = { ...user, age: 37 };
console.log(older); // { name: "Ada", age: 37 }
console.log(user);  // unchanged

不修改数组的方法

优先使用会返回新数组的方法:map、filter、concat 和 slice。避免使用会修改数组的方法,例如 push、splice 和原地 sort。

const a = [3, 1, 2];
const sorted = [...a].sort((x, y) => x - y);
console.log(sorted); // [1, 2, 3]
console.log(a);      // [3, 1, 2]

以不可变方式添加

不要使用 push,而应使用展开运算符或 concat 构建新数组。

const list = [1, 2];
const added = [...list, 3]; // not list.push(3)
console.log(added); // [1, 2, 3]

以不可变方式删除

请使用 filter 生成一个不包含指定元素的新数组,而不是使用 splice。

const list = [1, 2, 3, 4];
const without3 = list.filter((n) => n !== 3);
console.log(without3); // [1, 2, 4]

以不可变方式更新元素

要修改一个元素,请对数组使用 map,并为匹配的元素返回一个新值。

const todos = [{ id: 1, done: false }, { id: 2, done: false }];
const updated = todos.map((t) =>
  t.id === 1 ? { ...t, done: true } : t
);
console.log(updated[0].done); // true

浅拷贝与深拷贝

展开运算符只会复制一层。嵌套对象仍然是共享引用。要以不可变方式更新嵌套数据,请在每个要修改的层级使用展开运算符。

const state = { user: { name: "Ada", age: 36 } };
const next = {
  ...state,
  user: { ...state.user, age: 37 }
};
console.log(state.user.age); // 36
console.log(next.user.age);  // 37

使用冻结确保安全

Object.freeze 可以在运行时防止意外修改对象,从而明确表示不可变性(仅限一层)。

const config = Object.freeze({ env: "prod" });
config.env = "dev";       // ignored in non-strict mode
console.log(config.env);  // "prod"

Const 不等于不可变性

一个常见的误解是:const 只能防止重新赋值变量,不能防止修改变量所保存的值。使用 const 声明的数组仍然可以执行 push 操作。

const arr = [1, 2];
arr.push(3);          // allowed - value mutated
console.log(arr);     // [1, 2, 3]
// arr = [] would throw

好处回顾

不可变更新让变化跟踪变得非常简单(比较引用即可),支持撤销/重做,避免难以追踪的远距离影响,并且天然适合与纯函数配合使用。

const prev = { count: 0 };
const next = { ...prev, count: 1 };
console.log(prev === next); // false - easy to detect change

快速检查

避免修改。

回顾

不可变性意味着创建新值,而不是进行修改。使用展开运算符复制数组和对象,优先使用不修改数据的方法(map、filter、concat),并在嵌套更新时对每个层级使用展开运算符。请记住,const 会阻止重新赋值,但不会阻止修改;Object.freeze 可以提供运行时保护。不可变更新让变化检测和纯代码更容易实现。

常见问题解答

「避免修改原数据」课时是免费的吗?

是的 — 「避免修改原数据」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 JavaScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 JavaScript Academy 课程共包含 4 节课。

「避免修改原数据」这节课中我会学到什么?

使用副本,而不是直接修改数据。 你通过在浏览器中直接运行的动手代码来练习 JavaScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 JavaScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 JavaScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「避免修改原数据」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 JavaScript Academy 课中编写并运行代码吗?

能。每节 JavaScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 纯函数与副作用
  2. 声明式数据转换
  3. 避免修改原数据
  4. 无点风格
← 返回 JavaScript Academy