ES5 引入 屬性描述符 精細控制對象屬性行為,包含四大特性:
| 特性 | 含義 | 默認值 | 嚴格模式違規 |
|---|---|---|---|
| configurable | 能否 delete / 重新定義描述符 | false | TypeError |
| enumerable | 能否 for-in / Object.keys 枚舉 | false | 靜默忽略 |
| writable | 能否修改值 | false | TypeError |
| value | 屬性值 | undefined | - |
存取器描述符 (互斥數據描述符):get/set 函數,無 value/writable
// 嚴格模式下演示
"use strict";
const person = {};
// 僅定義 value,其餘特性默認 false
Object.defineProperty(person, 'name', { value: 'Scott' });
// person.name = 'John'; // TypeError: Cannot assign to read only property
// delete person.name; // TypeError: Cannot delete property
// 完全控制:可寫、可枚舉、可配置
Object.defineProperty(person, 'age', {
value: 25,
writable: true,
enumerable: true,
configurable: true
});
person.age = 26; // 成功
for (let k in person) console.log(k); // 輸出 age (name 不可枚舉)
// 存取器:計算屬性、驗證邏輯
let _age = 20;
Object.defineProperty(person, 'validatedAge', {
get() { return _age; },
set(v) { _age = Math.max(0, Math.min(150, v)); } // 限制 0-150
});
person.validatedAge = -1; console.log(person.validatedAge); // 0
person.validatedAge = 200; console.log(person.validatedAge); // 150
const person = {};
Object.defineProperties(person, {
name: { value: 'Scott', writable: false, enumerable: true },
address: { value: 'Beijing', writable: true, enumerable: true }
});
const desc = Object.getOwnPropertyDescriptor(person, 'name');
console.log(desc.configurable, desc.writable, desc.enumerable, desc.value);
// false false true 'Scott'
const human = { species: 'Human' };
const person = Object.create(human, {
name: { value: 'Scott', writable: true, enumerable: true, configurable: false },
gender: { get() { return 'Male'; } } // 僅 getter,不可寫
});
console.log(person.name); // Scott
console.log(person.gender); // Male
console.log(person.species); // Human (來自原型)
console.log(Object.getPrototypeOf(person) === human); // true
console.log(Object.getPrototypeOf(person) === human); // true
const arr = ['a','b','c'];
console.log(Object.keys(arr)); // ['0','1','2']
console.log(Object.getOwnPropertyNames(arr)); // ['0','1','2','length']
const obj = {};
Object.defineProperties(obj, {
a: { value: 1, enumerable: true },
b: { value: 2, enumerable: false }
});
console.log(Object.keys(obj)); // ['a']
console.log(Object.getOwnPropertyNames(obj)); // ['a','b']
| 方法 | 效果 | 檢測方法 | 可逆 |
|---|---|---|---|
| Object.preventExtensions(obj) | 禁止添加新屬性 | Object.isExtensible(obj) | 不可逆 |
| Object.seal(obj) | 防擴展 + 所有屬性 configurable=false | Object.isSealed(obj) | 不可逆 |
| Object.freeze(obj) | 密封 + 所有屬性 writable=false | Object.isFrozen(obj) | 不可逆 |
// 防擴展
const a = { x: 1 };
Object.preventExtensions(a);
a.y = 2; // 嚴格模式 TypeError
// 密封
const b = { x: 1 };
Object.seal(b);
b.x = 2; // 允許修改值
delete b.x; // TypeError
Object.defineProperty(b, 'x', { configurable: true }); // TypeError
// 凍結 (淺凍結)
const c = { x: 1, info: { age: 20 } };
Object.freeze(c);
c.x = 2; // TypeError
c.info.age = 21; // 成功!嵌套對象未凍結
// 深凍結需遞歸
function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach(k => {
if (obj[k] && typeof obj[k] === 'object') deepFreeze(obj[k]);
});
}
所有違規操作在嚴格模式 ("use strict") 下拋出 TypeError,非嚴格模式靜默失敗。強烈建議生產代碼全程啟用嚴格模式。
Object.freeze(config)Object.defineProperty(obj, 'prop', { get: () => value })Object.seal(module.exports)configurable: false 允許引擎優化

ES5 Object 靜態方法奠定了 JavaScript 元編程基石,配合嚴格模式能構建高安全性、高可維護性的代碼庫。理解描述符機制、原型繼承、擴展性控制,是現代 JS 開發者的必修課。