Object.defineProperty 通过设置 writable: false 实现对象属性只读,需配合 configurable: false 禁止修改、enumerable: false 隐藏枚举;它仅适用于对象属性,不能直接作用于变量;推荐用 const 声明常量,或结合 get/set 提供可控只读逻辑。

在 JavaScript 中,用 Object.defineProperty 将变量设为只读,本质是给对象的某个属性设置不可写(writable: false),同时通常还要禁用重新配置(configurable: false)和禁止枚举(enumerable: false)以增强只读性。注意:它不能直接让“变量”只读,只能作用于**对象的属性**。
设置对象属性为只读
这是最常用场景。通过 defineProperty 修改属性描述符,关闭 writable:
-
writable: false→ 赋值操作会被忽略(非严格模式)或抛错(严格模式) -
configurable: false→ 后续无法再用defineProperty改该属性,也不能delete -
enumerable: false(可选)→ 属性不会出现在for...in或Object.keys()中
示例:
const obj = {};
Object.defineProperty(obj, 'PI', {
value: 3.14159,
writable: false,
configurable: false,
enumerable: false
});
console.log(obj.PI); // 3.14159
obj.PI = 3; // 静默失败(非严格模式)或 TypeError(严格模式)
对已存在属性设为只读
如果属性已存在,需先确保 configurable: true(默认对象自有属性是可配置的),才能重新定义:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
const obj = { count: 10 };
Object.defineProperty(obj, 'count', {
writable: false,
configurable: false
});
obj.count = 20; // 无效
⚠️ 若原属性是 configurable: false,再次调用 defineProperty 修改 writable 会报错(除非同时改 value 且 writable 原为 true)。
模拟全局常量(不推荐但可行)
可通过修改全局对象(如 window 或 globalThis)添加只读属性:
Object.defineProperty(globalThis, 'API_URL', {
value: 'https://api.example.com',
writable: false,
configurable: false,
enumerable: true
});
但更推荐用 const 声明模块级常量,语义清晰、支持静态检查,且 Object.defineProperty 无法阻止 eval 或 with 等非常规手段篡改。
只读 + getter 的灵活方案
若需要动态计算或兼容旧环境,可用 get 描述符代替 value:
const obj = { _name: 'Alice' };
Object.defineProperty(obj, 'name', {
get() { return this._name; },
set() { throw new Error('name is read-only'); },
configurable: false,
enumerable: true
});
这样既防止赋值,又保留了读取逻辑的可控性,且 set 抛错比静默失败更利于调试。

















