javascript 对象的属性描述符(descriptor)

806 阅读2分钟

对象的属性描述符(descriptor)是什么?

我们在给对象添加属性的时候, 第一反应就是通过[key]: value 添加属性, 但其实这个value只是这个key属性的其中一种特性, 而描述当前这个对象属性特性的设置 就是属性描述符

其实_属性描述符_总共有四种:

  1. configurable: 是否可删除
  2. enumerable: 是否可枚举(遍历)
  3. value: 属性值
  4. writable: 是否可修改

当我们给window添加一个a属性时:

a = 1;

// 查看window 上的a
console.log(window)

// 读取window 上的a
console.log(window.a)

// 修改a的值
a = 2

大家有没有想过 为什么这个a属性 就能在window上看到, 也能读取到值, 也能修改?

可能大家觉得这是理所应当的, 我既然设置了 凭什么不能改? 现在 换一种写法: 利用Object.defineProperty添加属性:

// 给window添加aa属性 值为2
Object.defineProperty(window, 'aa', {
	value: 2,
})
console.log(window)
console.log('window.aa: ', window.aa)

打印后发现 window中 根本找不到aa属性, 但是却能读取到值。 在这里插入图片描述 而且其实不光看不到值, 也改不了, 也遍历不到这个aa属性:

// 修改aa属性:
window.aa = 3

// 打印a和aa属性:
for (const key in window) {
    if (['a', 'aa'].includes(key)) {
        console.log(key + ': ' + window[key])
    }
}
console.log(window);

// 删除aa属性
delete window.aa

在这里插入图片描述

直接添加属性 和 使用Object.defineProperty添加属性到底有什么区别呢?

我们通过Object.getOwnPropertyDescriptor这个方法来查看一下, 这个方法可以获取到当前这个对象属性的属性修饰符信息:

console.log(Object.getOwnPropertyDescriptor(window, 'a'));
console.log(Object.getOwnPropertyDescriptor(window, 'aa'));

在这里插入图片描述 ↑↑↑ 会发现除value值外, 第一个属性a的其他三个属性修饰符全部为true, 而属性aa则全为false 也就是说使用Object.defineProperty添加属性时, 除value外的属性修饰符 全部默认为false, 这才导致了上述现象的发生! 我们手动设置属性全部为true 再来看一下效果:

Object.defineProperty(window, 'aa', {
    value: 2,
    enumerable : true,
    configurable : true,
    writable: true
})

在这里插入图片描述 会发现 现在aa属性就正常了 也能查看 也能修改 也能遍历了~! 所以回头看一下 开头总结的四个_属性描述符_现在就能很好的理解了

其实, 通过上述四个属性来设置当前属性的特性, 这种设置属于 数据描述符, 还有一种叫 访问器描述符

访问器修饰符

其实就是用gettersetter替换掉了原先的valuewritable属性

Object.defineProperty(window, 'c', {
    get() {
        return this.a;
    },
    set(newValue) {
        this.a = newValue;
    },
    enumerable : true,
    configurable : true,
});

console.log(window.c, window);
console.log(Object.getOwnPropertyDescriptor(window, 'c'));

可以发现 使用set函数, 那就相当于 设置了writable: true, 而get函数 其实就是设置了value的返回值。

好啦 今天就和大家分享到这里啦~!!