避免修改原数据
使用副本,而不是直接修改数据。
避免修改原数据 是 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 反馈 — 无需本地设置。