对象的属性描述符(descriptor)是什么?
我们在给对象添加属性的时候, 第一反应就是通过[key]: value
添加属性, 但其实这个value
只是这个key属性的其中一种特性, 而描述当前这个对象属性特性的设置 就是属性描述符
其实_属性描述符_总共有四种:
configurable
: 是否可删除enumerable
: 是否可枚举(遍历)value
: 属性值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属性就正常了 也能查看 也能修改 也能遍历了~! 所以回头看一下 开头总结的四个_属性描述符_现在就能很好的理解了
其实, 通过上述四个属性来设置当前属性的特性, 这种设置属于 数据描述符
, 还有一种叫 访问器描述符
访问器修饰符
其实就是用getter
和setter
替换掉了原先的value
和writable
属性
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的返回值。
好啦 今天就和大家分享到这里啦~!!