深入理解Object.defineProperty

1. 定义及参数

MDN 对该Object.defineProperties()方法的定义:

Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

Object.defineProperty(obj, prop, descriptor)
  • 可接收三个参数:
  • obj:要定义属性的对象。
  • prop:要定义或修改的属性的名称或 Symbol 。
  • descriptor:要定义或修改的属性描述符。

2. 属性描述符分类

属性描述符主要有两种形式:数据描述符存取描述符

  • 数据描述符特有的两个属性:valuewritable
  • 存取描述符特有的两个属性:getset

两种形式的属性描述符不能混合使用,否则会报错,下面是一个错误的示范:

var obj = {};

var initName = ''

//TypeError: Invalid property descriptor. 
//Cannot both specify accessors and a value or writable attribute, #<Object>
Object.defineProperty(obj, "name", {
    value: 'new',
    writable: true,
    get: function(){
        console.log('get name')
        return initName
    },
    set: function(val){
        console.log('set name')
        initName = val
    }
});

我们简单想一下就能理解为什么两种描述不能混合使用;value用来定义属性的值,而getset同样也是定义和修改属性的值,两种描述符在功能上有明显的相似性

虽然数据描述符存取描述符不能混着用,但是他们均能分别和configrableenumerable一起搭配使用,下面表格表示了两种描述符可以同时拥有的健值:

在这里插入图片描述

3. Object.defineProperty() 使用

这是后续要操作的对象:

// 对象
const obj = {
  name: 'zhLeon521',
  age: 18
}

3.1 value(设置属性值)

给对象添加新的属性 height

Object.defineProperty(obj, 'height', {
    value: 666
})
console.log(obj) //{ name: 'zhLeon521', age: 18 }

这里描述符中的 value 值即是需要在对象上定义或者修改的属性值(如果对象上本身有该属性,则会进行修改操作);除了字符串,还可以是JavaScript的其他数据类型(数值,函数等)。

属性描述符是个对象,那么就有很多操作的地方了,它除了 value这个属性,还有以下:
在这里插入图片描述

3.2 writable(控制属性值是否可以修改)

Object.defineProperty() 中没有设置 writable 时,如果要去修改这里面的属性值,是没法被修改的(默认值为 false)。

在这里插入图片描述
Object.defineProperty() 中设置 writable: true 时,可以修改该属性值了。

在这里插入图片描述

2.3 enumerable(控制属性是否可枚举)

Object.defineProperty() 中没有设置 enumerable 时,如果要去遍历整个对象的键值,是没法遍历到通过 Object.defineProperty() 设置的属性值的。

在这里插入图片描述

Object.defineProperty() 中设置 enumerable: true 时,可以遍历到该属性值了。

在这里插入图片描述

2.4 configurable(控制对象是否可以重新配置操作事项)

我又有了新需求:上面我已经让对象可枚举了,然后我又想要通过一个新的 Object.defineProperty() 让属性值不可枚举。

如果什么都不设置的话,控制台是会报错的:
在这里插入图片描述
Object.defineProperty() 中设置 configurable: true 时,可以重新配置事项了。

在这里插入图片描述

2.5 get

  • get 方法是用来获取属性值。

get 方法中通过 return 返回设置的属性值,在 return 之前还可以进行一些逻辑操作:
在这里插入图片描述

2.6 set

  • set 方法是用来更新属性值。
  1. set 方法接收一个参数,这个参数就是设置的新的属性值,然后在方法中将这个新的值设置给自定义的属性。
  2. 一个错误的例子:
Object.defineProperty(obj, 'height', {
    // 设置新的属性值
    set(newValue) {
        console.log('任意设置时需要的自定义操作');
        this.height = newValue;
    }
});

obj.height = '111'

在这里插入图片描述

  1. 这个时候,控制台会报错,这是因为 set 方法本来就是监听 this.height(属性值) 的更新的的方法,当使用 this.height = newValue 这种方式给属性值赋新的值的话,就形成了一个递归,这个值更新了又更新。

  2. 正确的操作应该是在外面设置一个变量,将更新的值设置给这个变量,再用 get 方法来监听获取该变量的值。

let heightValue = '178';

Object.defineProperty(obj, 'height', {
    // 获取属性值
    get() {
        console.log('任意获取时需要的自定义操作');
        return heightValue;
    },
    // 设置新的属性值
    set(newValue) {
        console.log('任意设置时需要的自定义操作');
        heightValue = newValue;
    }
});

obj.height = '111'

console.log(obj.height);

在这里插入图片描述

4. 重点

对于 Object.defineProperty 来说,只可以对对象中的某一个属性进行监听,如果要监听整个对象的话,需要进行遍历。

const obj = {
    name: 'zhLeon521',
    age: 18,
    height: 178
}

for (const k in obj) {
    let value = obj[k];

    Object.defineProperty(obj, k, {
        // 获取属性值
        get() {
            console.log('任意获取时需要的自定义操作');
            return value;
        },
        // 设置新的属性值
        set(newValue) {
            console.log('任意设置时需要的自定义操作');
            value = newValue;
        }
    });


    console.log(value);
}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值