使用Object.freeze()可实现对象浅层不可变,深层不可变需递归封装deepFreeze函数;复杂场景推荐Immutable.js或immer库;结合扩展运算符可手动保持不可变性,选择方案应根据项目规模决定。

在JavaScript中,对象默认是可变的,但可以通过多种方式实现不可变性,确保数据不会被意外修改。关键在于合理使用内置方法和遵循函数式编程原则。
使用 Object.freeze() 实现浅层不可变
Object.freeze() 是最常用的方法之一,它能冻结对象,阻止属性的添加、删除和修改。
注意:它只作用于对象自身属性,属于浅层冻结。示例:
const user = {
name: 'Alice',
profile: { age: 25 }
};
Object.freeze(user);
user.name = 'Bob'; // 无效,严格模式下会报错
user.email = 'alice@example.com'; // 添加失败
// 但嵌套对象仍可变
user.profile.age = 30; // 成功!
实现深层不可变(Deep Freeze)
为了冻结嵌套对象,需要递归调用 Object.freeze()。
立即学习“Java免费学习笔记(深入)”;
可以封装一个 deepFreeze 函数:
function deepFreeze(obj) {
Object.getOwnPropertyNames(obj).forEach(prop => {
const value = obj[prop];
if (value && typeof value === 'object') {
deepFreeze(value);
}
});
return Object.freeze(obj);
}
const config = { api: { url: 'https://api.example.com' } };
deepFreeze(config);
config.api.url = 'https://hacked.com'; // 失败,已被深层冻结
使用 Immutable.js 或其他库
对于复杂场景,推荐使用成熟的不可变数据结构库,如 Immutable.js 或 immer。
本书是全面讲述PHP与MySQL的经典之作,书中不但全面介绍了两种技术的核心特性,还讲解了如何高效地结合这两种技术构建健壮的数据驱动的应用程序。本书涵盖了两种技术新版本中出现的最新特性,书中大量实际的示例和深入的分析均来自于作者在这方面多年的专业经验,可用于解决开发者在实际中所面临的各种挑战。
- Immutable.js 提供 Map、List 等不可变集合,每次操作返回新实例。
- immer 允许你以可变的方式编写代码,但生成不可变结果,适合处理复杂状态。
例如使用 immer:
import produce from 'immer';
const baseState = { users: [] };
const nextState = produce(baseState, draft => {
draft.users.push({ name: 'Charlie' }); // 看似可变,实际返回新对象
});
结合解构与扩展运算符进行安全更新
即使不使用额外工具,也可以通过扩展运算符手动保持不可变性。
常见做法:
- 更新对象:使用 { ...oldObj, newProp }
- 更新数组:使用 [...arr, newItem] 或 arr.filter() 等纯函数
示例:
const state = { count: 1 };
const newState = { ...state, count: state.count + 1 }; // 返回新对象
基本上就这些。选择哪种方式取决于项目复杂度。小型应用可用 Object.freeze 加规范约束,大型状态管理建议搭配 immer 或类似工具,既保证不可变性又提升开发体验。









