5.2.1保护属性
【1】定义
es5中,对象中中的每个属性,不再只是一个简单的值,还有三个相关的开关。
eid:{
value:属性值,
writable:true,
enumerable:false,
configurable:false
}
- writable : true/false 控制当前属性值是否可以修改
- enumerable : true/false 控制是否可用for in遍历到这个属性
- configurable : true/false ①控制是否可删除当前属性,②控制是否可修改前两个开关
【2】如何修改开关
1)只修改一个属性的开关
i:Object.defineProperty(对象名,“属性名”,{
开关:true或false
… : …
})
ii:强调:今后,只要修改writable和enumerable两个开关时, 都要同时修改configurable:false,阻止别人的程序重新打 开我们关闭的开关(configurable:false是不可逆的)
2)修改多个属性的开关
Object.defineProperties(对象名,{
属性名1:{
开关名: true或false,
... : ...
},
属性名2:{
开关名: true或false,
... : ...
},
})
示例:
var eric={
ename:"艾瑞克",
eage:27
}
Object.defineProperty(eric,"eage",{
// 可以修改eage的值
writable:true,
// 不能让外界for in遍历到
enumerable:false,
// 不可以删除
configurable:false
})
【3】访问器属性
想要灵活的自定义规则保护属性值,三个开关都不适用了。这时候使用访问器属性
i:什么是访问器属性:
自己不保存属性值,只提供对另一个数据属性的保护。——保镖
ii:如何定义访问器属性:2步
1)定义小黑屋属性,转移原对象中原属性的值
Object.defineProperty(原对象,"小黑屋",{
value:原对象.要保护的属性,
writable:true,
enumerable:false, //小黑屋不能轻易被人发现
configurable:false //小黑屋不可删除
})
2)定义访问器属性(替身+2个保镖)
Object.defineProperty(原对象,"要保护的原属性名",{
get:function(){
//this->访问器属性eage所在的当前对象->eric
return this.小黑屋;
},
set:function(value){
if(判断条件){
this.小黑屋=value;
}else{
throw Error("自定义错误提示");//复习第一阶段try catch异常处理
}
},
//访问器属性自己不存值,只提供保护,所以没有value属性
//正是因为writable不好用,我们才被迫用访问器属性代替writable,所以用了get/set,就不用writable。
//因为替身必须替真实属性抛头露面,所以,必须可以被for in发现
enumerable:true,
//因为替身不能随意删除,所以
configurable:false
})
iii:外界如何使用访问器属性:和使用对象的普通属性完全一样
1). 获取属性值: 对象.属性名
在底层: 自动调用访问器属性的get()
2). 修改属性值: 对象.属性名=新值
底层: 自动调用访问器属性的set(),将新值传给()中的value形参。
【4】示例:
// 访问器属性
var eric={
ename:"艾瑞克",
eage:27
}
// 规定:年龄可以修改,必须在18-65之间
// 定义小黑屋,用于保存真正的属性值
Object.defineProperty(eric,"小黑屋",{
// 值为真正的对象中的属性名
value:eric.eage,
// 可以修改eage的值
writable:true,
// 不能让外界for in遍历到
enumerable:false,
// 不可以删除
configurable:false
})
// 定义替身+2个保镖(get和set)
Object.defineProperty(eric,"eage",{
// get获取小黑屋中真正的值
get:function(){
return this.小黑屋;
},
// set可以将外界想要修改的值传入到小黑屋
set:function(value){
if(value>=18&&value<=65){
this.小黑屋=value;
}else{
throw Error("年龄超出范围");
}
},
// 访问器属性自己不存值,只提供保护,所以没有value属性
// 替身不可以有writable,正是因为writable不好用才使用的访问器属性
// 替身可以for in遍历到
enumerable:true,
// 替身不可以被删除
configurable:false
})
console.log(eric.eage);
eric.eage=30;
console.log(eric.eage);
eric.eage=80;
console.log(eric.eage);