深入理解 JavaScript 属性描述对象
jstutorial Javascript tutorial book 项目地址: https://gitcode.com/gh_mirrors/js/jstutorial
属性描述对象(Attributes Object)是 JavaScript 中一个重要的内部机制,它决定了对象属性的行为和特性。本文将全面解析属性描述对象的各个方面,帮助开发者更好地控制和管理对象属性。
属性描述对象基础
属性描述对象是 JavaScript 用来描述对象属性的元信息的数据结构。每个属性都有对应的属性描述对象,包含以下6个元属性:
{
value: 123, // 属性值
writable: true, // 是否可写
enumerable: true, // 是否可枚举
configurable: true, // 是否可配置
get: undefined, // 取值函数
set: undefined // 存值函数
}
这些元属性共同决定了属性的行为特征。例如,writable
为false
时,属性值不可修改;enumerable
为false
时,属性不会被for...in
循环遍历。
操作属性描述对象的方法
获取属性描述
Object.getOwnPropertyDescriptor()
方法可以获取对象自身属性的描述对象(不包括继承的属性):
const obj = { name: 'John' };
const desc = Object.getOwnPropertyDescriptor(obj, 'name');
// {
// value: "John",
// writable: true,
// enumerable: true,
// configurable: true
// }
定义和修改属性
Object.defineProperty()
和Object.defineProperties()
用于定义或修改属性:
const obj = {};
Object.defineProperty(obj, 'readOnlyProp', {
value: 42,
writable: false
});
obj.readOnlyProp = 100; // 静默失败(严格模式下报错)
console.log(obj.readOnlyProp); // 42
注意,使用这些方法时,属性描述对象中的writable
、enumerable
和configurable
默认为false
,与直接赋值时不同。
属性特性详解
value 和 writable
value
存储属性值,writable
决定该值是否可修改。当writable
为false
时:
- 非严格模式下,修改操作静默失败
- 严格模式下会抛出TypeError
'use strict';
const obj = {};
Object.defineProperty(obj, 'x', { value: 1, writable: false });
obj.x = 2; // TypeError: Cannot assign to read only property 'x'
enumerable
enumerable
决定属性是否可枚举,影响以下操作:
for...in
循环Object.keys()
JSON.stringify()
const obj = { a: 1, b: 2 };
Object.defineProperty(obj, 'c', { value: 3, enumerable: false });
console.log(Object.keys(obj)); // ['a', 'b']
console.log(JSON.stringify(obj)); // '{"a":1,"b":2}'
configurable
configurable
决定属性是否可配置,当为false
时:
- 不能删除属性
- 不能修改属性描述(除
value
和writable
从true
改为false
)
const obj = {};
Object.defineProperty(obj, 'x', {
value: 1,
configurable: false
});
delete obj.x; // false(静默失败)
Object.defineProperty(obj, 'x', { enumerable: false }); // TypeError
存取器属性
除了数据属性,JavaScript 还支持存取器属性(accessor properties),通过get
和set
定义:
const obj = {
_name: 'John',
get name() {
return this._name;
},
set name(value) {
if (value.length > 3) {
this._name = value;
}
}
};
obj.name = 'Alice'; // 设置成功
obj.name = 'Li'; // 设置失败(长度不足)
注意:存取器属性不能与value
或writable
同时存在。
对象状态控制
JavaScript 提供了三个方法来控制对象状态,限制属性的增删改:
Object.preventExtensions()
- 禁止添加新属性Object.seal()
- 禁止添加/删除属性(相当于preventExtensions
+所有属性configurable:false
)Object.freeze()
- 禁止任何修改(相当于seal
+所有属性writable:false
)
对应的检查方法:
Object.isExtensible()
Object.isSealed()
Object.isFrozen()
const obj = { x: 1 };
Object.freeze(obj);
obj.x = 2; // 静默失败(严格模式下报错)
obj.y = 2; // 静默失败
delete obj.x; // 静默失败
实际应用场景
-
创建常量属性:
const config = {}; Object.defineProperty(config, 'API_URL', { value: 'https://api.example.com', writable: false, configurable: false });
-
隐藏内部实现细节:
function createCounter() { let count = 0; return Object.defineProperties({}, { value: { get: () => count, enumerable: true }, increment: { value: () => ++count, enumerable: true } }); }
-
防止对象被意外修改:
const constants = Object.freeze({ PI: 3.14159, E: 2.71828 });
注意事项
- 原型链上的属性不受这些限制影响
- 冻结对象时,嵌套对象不会被自动冻结
- 性能考虑:频繁操作属性描述对象可能影响性能
理解属性描述对象是掌握 JavaScript 对象高级用法的关键,它为实现各种设计模式(如不可变对象、属性验证等)提供了基础支持。
jstutorial Javascript tutorial book 项目地址: https://gitcode.com/gh_mirrors/js/jstutorial
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考