属性分为两种:数据属性和访问器属性。
1.数据属性
数据属性
包含一个保存数据值的位置,值会从这个位置读取,也会写入到这个位置,数据属性又4个特性描述它们的行为。
Configurable
:表示属性是否可以通过delete
删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,所有直接定义在对象上的属性这个特性都是true
。Enumberable
:表示属性是否可以通过for-in
循环返回。默认情况下,所有直接定义在对象上的属性这个特性都是true
。Writable
:表示属性的值是否可以被修改。默认情况下,所有直接定义在对象上的属性的这个特性都是true
。Value
:表示属性实际的值。这个特性的默认值为undefined
。
要修改属性的默认特性,就必须使用
Object.defineProperty()
方法,这个方法接收3个参数:
- 要给其添加属性的对象
- 属性的名称
- 和一个描述符对象,即描述符对象上的属性包含:
configurable
、enumerbale
、writable
和value
。
writable:false
let obj={}
Object.defineProperty(obj,'name',{
writable:false,//但该属性此时是只读的
value:'修改后的名字'
})
console.log(obj.name);//修改后的名字
obj.name='writable设置为false,不可修改属性的值'
console.log(obj.name);//修改后的名字
- 属性设置为不可被修改
enumerable:false
let obj1={name:1234,age:12}
Object.defineProperty(obj1,'name',{
enumerable:false
})
// 此时只能读取到age,name是无法通过for-in访问到的。
for (const key in obj1) {
console.log(key);//age
}
- 此时
for-in
是访问不到name
的
2. 访问器属性
访问器不包含数据值。它们包含一个获取
getter
函数和一个设置setter
函数。
- 在
读取
访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。- 在
写入
访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。访问器属性4个特性
Configurable
:表示属性是否可以通过delete
删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,所有直接定义在对象上的属性这个特性都是true
。Enumberable
:表示属性是否可以通过for-in
循环返回。默认情况下,所有直接定义在对象上的属性这个特性都是true
。Get
:获取函数,在读取属性时调用。默认值为undefined
。Set
:设置函数,在写入属性时调用。默认值为undefined
。
let book={
year_:2020,//year_下划线常用来表示该属性并不希望在对象外部被访问。
edition:1
}
Object.defineProperty(book,'year',{
// 获取属性值返回year的值
get(){
return this.year_
},
// 设置属性值
set(newValue){
if(newValue>2020){
this.year_=newValue
this.edition=newValue + 1-2020 //设置一个属性值会导致一些其他变化发生。
}
}
})
book.year=2021
console.log(book.edition);//2
console.log(book.year);//2021
- 当前设置
book.year
的值,对应的book.edition的
值也会发生改变。
访问器属性的典型使用场景:
设置一个属性值会导致一些其他变化发生。
看到这里,可以更好地理解vue
中的双向数据绑定原理了,尤其是计算属性computed
……
3. 定义多个属性Object.defineProperties()
在一个对象上同时定义多个属性的可能性是非常大的。
Object.defineProperties()
接收两个参数:
- 要为之添加或修改属性的对象
- 描述符对象,其属性与要修改的属性
一一
对应。
let notebook={}
Object.defineProperties(notebook,{
// _下划线常用来表示该属性并不希望在对象外部被访问
year_:{
value:2021
},
edition:{
value:1
},
year:{
get(){
return this.year_
},
set(newValue){
if(newValue>2020){
this.year_=newValue
this.edition=newValue + 1-2020
}
}
}
})
4. 读取属性
使用
Object.getOwnPropertyDescriptor()
方法可以取得指定属性的属性描述符。 这个方法接收两个参数:
- 属性所在的对象
- 要取得其描述符的属性名。
- 返回值是一个对象,对于访问器属性包含 configurable 、 enumerable 、 get 和 set 属性。
let descriptor=Object.getOwnPropertyDescriptor(notebook,'year_')
console.log(descriptor);
console.log(descriptor.value);//2020
console.log(descriptor.configurable);//false
ECMAScript 2017新增了
Object.getOwnPropertyDescriptors() 静态方法
。这个方法
实际上会在每个自有属性上调用Object.defineProperties()
并在一个新对象中返回它们。
console.log(Object.getOwnPropertyDescriptors(notebook));