小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。 本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
前言
吃饱饭才有力气写代码~
上次聊了聊对象属性中的数据属性中的四类特性,除此之外属性还有一类是访问器熟悉,接下来记录总结一下。
访问器属性不包含数据值,它们包含一个获取函数(getter)和一个设置(setter)函数,但是它俩并不是必须的。获取函数是在读取访问器属性时调用,负责返回一个有效的值;在写入访问器属性时会调用设置函数传入新的值,这个函数决定对数据作出怎样的修改。访问器也有四个特性来描述各自的行为:
- [[Configurable]] 表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性以及是否可以把它改为访问器属性,默认情况下所有直接定义在对象上的属性的这个特性都是true。
- [[Enumerable]] 表示属性是否可以通过for-in循环返回,默认情况下所有直接定义在对象上的属性的这个特性都是true。
- [[Get]] 获取函数,在读取属性时调用,默认值为undefined。
- [[Set]] 设置函数,在读取属性时调用,默认值为undefined。 和数据属性一样,访问器属性也是不能直接定义的,需要使用Object.defineProperty()方法,比如下面这个例子:
let book = {
year_: 2017,//私有成员
edition: 1 //公共成员
};
Object.defineProperty(book,"year",{
get(){
return this.year_;
},
set(){
if(newValue > 2017){
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
});
book.year = 2018;
console.log(book.edition)//2
在上面这个例子里,book 对象有两个默认属性:year_和edition(year_的下划线常用来表示这个属性不希望在对象方法的外部被访问);另一个属性year被定义为一个访问器属性,设置函数会做一些计算来决定edition的值,获取函数会返回year_的值,因此 book.year = 2018;会使year_的值变为2018,edition变为2。这就是访问器典型的使用场景,也就是设置一个属性的值,从而导致其它一些发生变化;
注意:
获取函数和设置函数不一定都要定义,只定义获取函数意味着属性只读,此时尝试修改属性会抛出错误;类似地只定义设置函数的属性不能读取。
定义多个属性的方法
Object.defineProperties()这个方法可以通过多个描述符一次性定义多个属性,接收两个参数:要添加或修改属性的对象和一个描述符对象:
let book = {};
Object.defineProperties(book,{
year_: {
value: 2017
},
edition: {
value: 1
},
year:{
get(){
return this.year_;
},
set(){
if(newValue > 2017){
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
},
});
读取属性特性的方法
就上面定义的对象读取它的相关属性,用到的方法是 Object.getOwnPropertyDescriptor(),比如:
let descriptor = Object.getOwnPropertyDescriptor(book,"year_");
console.log(descriptor.value);// 2017
console.log(descriptor.configurable);// false
console.log( typeof descriptor.get);// "undefined"
let descriptor = Object.getOwnPropertyDescriptor(book,"year");
console.log(descriptor.value);// undefined
console.log(descriptor.configurable);// false
console.log( typeof descriptor.get);// "function"
新增了Object.getOwnPropertyDescriptors()静态方法,这方法会在每个自有属性上调用 Object.defineProperties() 并在一个新对象中返回,如下:
//上述例子定义的book
console.log(Object.getOwnPropertyDescriptors(book));
//{
// edition:{
// configurable: false,
// enumerable: false,
// value: 1,
// writeable: false
// },
// year:{
// configurable: false,
// enumerable: false,
// get: f(),
// set: f(newValue)
// },
// year_:{
// configurable: false,
// enumerable: false,
// value: 2019,
// writeable: false
// },
//}
总结
还有很多方法,且听下回分解~