JavaScript中无法真正实现不可变变量,但可通过Object.defineProperty设置writable、configurable、enumerable均为false使对象属性具备逻辑不可变性;该方法仅适用于对象属性,不作用于原始值;需配合Object.freeze实现全面保护,且与const声明(绑定不可变)作用层级不同。

JavaScript 中没有真正意义上的“不可变变量”,但可以通过 Object.defineProperty 配合属性描述符,让对象的某个属性表现为只读、不可删除、不可重新配置,从而实现**逻辑上的不可变性**。注意:这仅作用于对象属性,对原始值(如数字、字符串)本身无效。
设置只读、不可配置、不可删除的属性
关键在于将 writable、configurable、enumerable 全部设为 false:
- writable: false —— 属性值不能被修改
-
configurable: false —— 属性不能被删除,也不能再次用
defineProperty修改其描述符(包括改回可写) -
enumerable: false —— 属性不会出现在
for...in循环或Object.keys()中(可选,根据需求设为true也可)
示例:
const obj = {};
Object.defineProperty(obj, 'PI', {
value: 3.14159,
writable: false,
configurable: false,
enumerable: true
});
console.log(obj.PI); // 3.14159
obj.PI = 3; // 无效(非严格模式静默失败;严格模式报 TypeError)
delete obj.PI; // false(非严格模式返回 false;严格模式报 TypeError)
Object.defineProperty(obj, 'PI', { writable: true }); // 报 TypeError
封装成“常量式”定义工具函数
重复写 defineProperty 较繁琐,可封装一个简易的常量定义函数:
立即学习“Java免费学习笔记(深入)”;
function defineConstant(obj, key, value) {
Object.defineProperty(obj, key, {
value,
writable: false,
configurable: false,
enumerable: true
});
}
const MathConstants = {};
defineConstant(MathConstants, 'MAX_SAFE_INTEGER', Number.MAX_SAFE_INTEGER);
defineConstant(MathConstants, 'E', Math.E);
注意:它不冻结整个对象
Object.defineProperty 只保护指定属性,不影响对象其他属性:
- 对象仍可添加新属性(除非对象本身被
Object.preventExtensions()限制) - 其他已有属性仍可能被修改或删除(除非也单独定义为不可变)
- 若需全面保护,应配合
Object.freeze()—— 它内部正是批量调用defineProperty实现的
与 const 声明的区别
const 声明的是**绑定不可重新赋值**,不是值不可变:
-
const x = 5;→x = 10报错(绑定不可变) -
const obj = {};→obj.a = 1合法(对象内容仍可变) -
Object.defineProperty控制的是**对象属性的行为**,和const作用层级不同,二者可结合使用


















