属性描述符:它表达了一个属性的相关信息(元数据)(本质上是一个对象)
属性是存在于对象之中,我们知道,对象有属性名和属性值,除了这些之外,还有一些相关信息,比如可以枚举的,可修改的等等,我们称之为属性描述符。
1.数据属性:
就是平时定义对象属性那些,如:
const phone = {brand: '小米'} //初始化的时候写的
phone.price = 3999; //后来写的
phone.system = function(){console.log('MIUI');} //甚至是函数
通过Object.getOwnPropertyDescriptors(对象); //可以得到一个对象的所有属性描述符。
通过Object.getOwnPropertyDescriptor(对象, 属性名)
可以得到一个对象的某个属性的属性描述符,它包括:
value:属性值
configurable:该属性的描述符本身是否可以修改
enumerable:该属性是否可以被枚举
writable:该属性的值是否可以被重新赋值
Object.getOwnPropertyDescriptors(对象)可以得到某个对象的所有属性描述符
如果需要为某个对象添加属性时 或 修改属性时, 配置其属性描述符,可以使用下面的代码:
Object.defineProperty(对象, 属性名, 描述符);
Object.defineProperties(对象, 多个属性的描述符)
2.存取器属性:
属性描述符中,如果配置了 get 和 set 中的任何一个,则该属性,不再是一个普通属性,而变成了存取器属性。
get 和 set配置均为函数,如果一个属性是存取器属性,则读取该属性时,会运行get方法,将get方法得到的返回值作为属性值;如果给该属性赋值,则会运行set方法。
const phone = {
brand: '小米',
price: 3999,
system: 'MIUI',
}
Object.defineProperty(phone, 'price', {
get() { //这里用了下速写函数的方式,即 get:function(){...}
console.log('get!!');
},
set() {
console.log('set!!');
}
});
phone.price; //调用了get方法
phone.price = 123;
console.log(price); //undefined, 它只是调用了set方法,而set方法没返回任何东西。所以undefined
phone.price = price + 1; //undefined + 1 == NaN; 先调用get方法,再调用set方法
console.log(phone.price); //undefined; 调用了get方法
图片.png
其实DOM元素很多属性都是存取器属性:
它们都没办法直接显示出来,要显示就要调用方法。。
const div = document.querySelector('div');
console.dir(div); //将对象结构打印出来
图片.png
存取器属性最大的特点就是,不是像之前的属性一样放在内存空间里面,以前的变量啊属性啊都是放在内存空间里面的;
变成存取器属性后,没有一块专门的内存空间来放数据了。变成了运行属性调用get函数,给属性赋值调用set函数。
运行以下代码会直接卡死。。
Object.defineProperty(phone, 'price', {
get() {
console.log(this.price); //栈溢出。。。
return phone.price; //递归了。。
},
set(val) {
console.log('set!!', val);
phone.price = val; //递归了。。。
}
});
phone.price = 666;
所以在get方法里面不要读取该属性本身,在set方法里面不要给该属性本身赋值。好歹你也加个_(下划线)。暗示:内部属性。
存取器属性最大的意义,在于可以控制属性的读取和赋值。
小demo:
小米10价格:<span>0</span>
<script>
const span = document.querySelector('span');
const phone = {
brand: '小米',
price: 3999,
}
Object.defineProperty(phone, 'price', {
get() {
return span.innerText;
},
set(val) {
span.innerText = val; //给DOM添加文本
}
});
phone.price = 1998; //运行了set函数
</script>
注意:
写了get 或 set 就不能在defineProperty里面写 value 或 writable 了,
Object.defineProperty(phone, 'price', {
value:123, //直接报错
get() {},
set(val) {}
});
因为配置了get 或 set之后,它变成一个存取器属性,本身就没有内存空间来放数据,是调用一个函数。
而value 和 writable表示的是内存空间里面的数据。。矛盾了。







网友评论