Skip to content

获取属性描述符

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 方法用于获取对象某个特定属性的描述符。它接受两个参数:

  1. 对象(Object):要查询的对象。
  2. 属性名(String 或 Symbol):要获取描述符的属性名。

返回值是一个属性描述符对象,包含以下属性:

  • value:属性的值。
  • writable:布尔值,表示属性是否可写。
  • enumerable:布尔值,表示属性是否可枚举。
  • configurable:布尔值,表示属性描述符是否可配置。

getOwnPropertyDescriptors

getOwnPropertyDescriptors 方法用于获取对象所有自身属性的描述符。它只接受一个参数:

  1. 对象(Object):要查询的对象。

返回值是一个对象,其中每个键是对象的属性名,值是对应属性的描述符对象。

设置属性描述符

Object.defineProperty

Object.defineProperty 是 JavaScript 中用于定义或修改对象属性的方法。它接受三个参数:

  1. 对象(Object):要定义或修改属性的对象。
  2. 属性名(String 或 Symbol):要定义或修改的属性名。
  3. 属性描述符(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.sealObject.freeze 是 JavaScript 中用于控制对象可变性的两个方法,它们有一些相似之处,但也有重要的区别。

Object.seal

Object.seal 方法用于密封一个对象。密封对象的主要效果是:

  1. 不可添加新属性:密封后的对象不能添加新属性。
  2. 不可删除现有属性:密封后的对象不能删除现有属性。
  3. 现有属性可修改:密封后的对象的现有属性可以被修改(如果它们是可写的)。
  4. 属性描述符不可配置:密封后的对象的属性描述符不能被更改(即 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 方法用于冻结一个对象。冻结对象的主要效果是:

  1. 不可添加新属性:冻结后的对象不能添加新属性。
  2. 不可删除现有属性:冻结后的对象不能删除现有属性。
  3. 不可修改现有属性:冻结后的对象的现有属性不能被修改(即使它们是可写的)。
  4. 属性描述符不可配置:冻结后的对象的属性描述符不能被更改(即 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