Object.defineProperty()小结

434 阅读3分钟

每天做个总结吧,坚持就是胜利!

    /**
        @date 2021-06-19
        @description Object.defineProperty()小结
    */

壹(序)

Object的defineProperty方法,用于在一个对象上新增或修改属性,通过Object.defineProperty()调用,而不是在一个对象实例上调用,因为它是Object的直接方法,而不是prototype上的方法。

defineProperty方法接受三个参数:

  1. 需要处理的对象(obj);

  2. 该对象需要处理的属性名或Symbol(prop);

  3. 需要修改的属性描述符(descriptor(); ) 返回完成操作后的对象。

贰(与.操作符或[]操作符区别)

对象也能使用.操作符或[]操作符去新增或修改一个属性,但是使用defineProperty能够进行更多的操作,比如该属性是否可枚举(enumerable),是否可配置(configurable)等,主要在于第三个参数;

descriptor(描述符)分为两种,数据描述符与存取描述符;

传入的描述符只能是其中一种,两种描述符共同的参数是:

/** 
* enumerable: 是否可枚举(能否使用for...inObject.keys()读取),默认为false;
* configurable: 是否可配置,能否修改描述符,能否删除,默认为false;
*/

而数据描述符特有的参数是:

/**
* value: 当前对象当前属性的值,默认为undefined;
* writable: 是否可写(能否修改value),默认为false;
*/

// 测试
const obj = {};

Object.defineProperty(obj, 'a', {
    enumerable: true,
    configurable: true,
    value: 1,
    writable: true,
})

Object.keys(obj); // ['a']

Object.defineProperty(obj, 'a', {
    enumerable: false,
    configurable: true,
    value: 1,
    writable: true,
})

Object.keys(obj); // []

obj.a = 2;
console.log(obj); // {a: 2}

Object.defineProperty(obj, 'a', {
    enumerable: false,
    configurable: true,
    value: 1,
    writable: false,
})

obj.a = 2;
console.log(obj); // {a: 1}

Object.defineProperty(obj, 'b', {
    enumerable: false,
    configurable: false,
    value: 1,
    writable: false,
})

delete obj.a; // true
delete obj.b; // false

存取描述符特有的参数是:

/**
* get: 属性的getter函数,必须是一个函数,否则报错,如果没有此函数则返回undefined
*      有的话调用此函数,返回函数返回值;默认为undefined;
* set: 属性的setter函数,也必须是一个函数,否则报错,修改属性值时调用此函数
*      此函数中this是当前对象;默认为undefined
*/

// 测试
const obj = {};
let value = 1;

Object.defineProperty(obj, 'b', {
    enumerable: true,
    configurable: true,
    get: function() {
        return value;
    },
    set: function(newValue) {
        value = newValue * newValue;
    },
})

console.log(obj.b); // 1

obj.b = 2;
console.log(obj.b); // 4

叁(引申,来自《你不知道的JS上》)

  1. 对象常量
/**
* 将一个对象的属性设置成一个常量(不可修改,不可删除)
*/
const obj = {};

Object.defineProperty(obj, 'a', {
    value: 1,
    writable: false,
    configurable: false,
    enumerable: true, // 原文没有,自己认为需要是可枚举的
})
  1. 禁止扩展
/**
* 禁止一个对象添加新属性,可以使用Object.preventExtensions()
*/
const obj = {a: 1};

Object.preventExtensions(obj);

console.log(obj); // {a: 1}

obj.b = 2;

console.log(obj); // {a: 1}


  1. 密封
/**
* 使用Object.seal()将一个对象密封起来,该对象将不能添加,删除属性,也不可重新配置,可以修改
* 实际上是调用Object.preventExtensions()以及设置所有属性的configurable为false
*/
  1. 冻结
/**
* 使用Object.freeze()可以将一个对象冻结,该对象将不能添加,修改,删除,配置
* 实际上是调用Object.seal()并把所有的数据访问属性的writable置为false
* 注意,getter和setter是不受影响的,其次,是可以修改该对象的引用属性的。
*/
const obj = {a: 1, c: {d: 3}};
let b = 2;

Object.defineProperty(obj, 'b', {
    get: function() { return b },
    set: function(val) { b = val }
});

Object.freeze(obj);

obj.a = 3;

console.log(obj.a); // 1

obj.b = 4;
console.log(obj.b); // 4

obj.c.d = 5;
console.log(obj.c.d); // 5