获取属性描述符
javascript
// 获取对象某个属性的描述符
Object.getOwnPropertyDescriptor(obj, 'name')
// {value: 'jukaifeng', writable: true, enumerable: true, configurable: true}
// 获取对象的全部属性描述符
Object.getOwnPropertyDescriptors(obj)
// {name: {value: 'jukaifeng', writable: true, enumerable: true, configurable: true}, age: {value: 25, writable: true, enumerable: true, configurable: true}, gender: {value: 'Male', writable: true, enumerable: true, configurable: true}, hobby: {value: ['reading', 'running', 'coding'], writable: true, enumerable: true, configurable: true}}
getOwnPropertyDescriptor
getOwnPropertyDescriptor
方法用于获取对象某个特定属性的描述符。它接受两个参数:
- 对象(Object):要查询的对象。
- 属性名(String 或 Symbol):要获取描述符的属性名。
返回值是一个属性描述符对象,包含以下属性:
value
:属性的值。writable
:布尔值,表示属性是否可写。enumerable
:布尔值,表示属性是否可枚举。configurable
:布尔值,表示属性描述符是否可配置。
getOwnPropertyDescriptors
getOwnPropertyDescriptors
方法用于获取对象所有自身属性的描述符。它只接受一个参数:
- 对象(Object):要查询的对象。
返回值是一个对象,其中每个键是对象的属性名,值是对应属性的描述符对象。
设置属性描述符
Object.defineProperty
Object.defineProperty
是 JavaScript 中用于定义或修改对象属性的方法。它接受三个参数:
- 对象(Object):要定义或修改属性的对象。
- 属性名(String 或 Symbol):要定义或修改的属性名。
- 属性描述符(Object):描述属性的特性。属性描述符可以是数据描述符或存取描述符。
数据描述符
数据描述符是一个具有值的属性,该值可能是可写的,也可能不是。数据描述符可以包含以下属性:
value
:属性的值,默认为undefined
。writable
:布尔值,表示属性是否可写,默认为false
。enumerable
:布尔值,表示属性是否可枚举,默认为false
。configurable
:布尔值,表示属性描述符是否可配置,默认为false
。
javascript
const obj = {};
Object.defineProperty(obj, 'name', {
value: 'John',
writable: true,
enumerable: true,
configurable: true
});
console.log(obj.name); // 输出: John
obj.name = 'Doe';
console.log(obj.name); // 输出: Doe
存取描述符
存取描述符是由 getter 和 setter 函数描述的属性。存取描述符可以包含以下属性:
get
:一个函数,当访问该属性时会被调用,返回值为属性的值,默认为undefined
。set
:一个函数,当修改该属性时会被调用,接受一个参数,即新的属性值,默认为undefined
。enumerable
:布尔值,表示属性是否可枚举,默认为false
。configurable
:布尔值,表示属性描述符是否可配置,默认为false
。
javascript
const obj = {};
Object.defineProperty(obj, 'name', {
get() {
return this._name;
},
set(value) {
this._name = value;
},
enumerable: true,
configurable: true
});
obj.name = 'John';
console.log(obj.name); // 输出: John
Object.defineProperties
javascript
Object.defineProperties(obj, {
age: {
get() {
return this._age;
},
set(value) {
this._age = value;
}
},
gender: {
get() {
return this._gender;
},
set(value) {
this._gender = value;
}
},
hobby: {
get() {
return this._hobby;
},
set(value) {
this._hobby = value;
}
}
})
冻结与密封对象
js
Object.freeze(obj) // 冻结对象,使其不可修改
Object.seal(obj) // 密封对象,使其不可配置
Object.seal
和 Object.freeze
是 JavaScript 中用于控制对象可变性的两个方法,它们有一些相似之处,但也有重要的区别。
Object.seal
Object.seal
方法用于密封一个对象。密封对象的主要效果是:
- 不可添加新属性:密封后的对象不能添加新属性。
- 不可删除现有属性:密封后的对象不能删除现有属性。
- 现有属性可修改:密封后的对象的现有属性可以被修改(如果它们是可写的)。
- 属性描述符不可配置:密封后的对象的属性描述符不能被更改(即
configurable
属性变为false
)。
示例:
javascript
const obj = { name: 'John', age: 30 };
Object.seal(obj);
obj.name = 'Doe'; // 允许修改现有属性
console.log(obj.name); // 输出: Doe
delete obj.age; // 不允许删除现有属性
console.log(obj.age); // 输出: 30
obj.hobby = 'Reading'; // 不允许添加新属性
console.log(obj.hobby); // 输出: undefined
Object.freeze
Object.freeze
方法用于冻结一个对象。冻结对象的主要效果是:
- 不可添加新属性:冻结后的对象不能添加新属性。
- 不可删除现有属性:冻结后的对象不能删除现有属性。
- 不可修改现有属性:冻结后的对象的现有属性不能被修改(即使它们是可写的)。
- 属性描述符不可配置:冻结后的对象的属性描述符不能被更改(即
configurable
属性变为false
)。
示例:
javascript
const obj = { name: 'John', age: 30 };
Object.freeze(obj);
obj.name = 'Doe'; // 不允许修改现有属性
console.log(obj.name); // 输出: John
delete obj.age; // 不允许删除现有属性
console.log(obj.age); // 输出: 30
obj.hobby = 'Reading'; // 不允许添加新属性
console.log(obj.hobby); // 输出: undefined
总结
Object.seal
允许修改现有属性,但不能添加新属性或删除现有属性。Object.freeze
不仅不能添加新属性或删除现有属性,还不能修改现有属性。
选择使用哪个方法取决于你需要对对象施加的可变性控制程度。如果你只需要防止添加和删除属性,但允许修改属性,可以使用 Object.seal
。如果你需要完全锁定对象,使其完全不可变,可以使用 Object.freeze
。