引言
如果我们希望对JS中的一个属性进行比较精确的操作控制就需要使用到属性描述符
,通过属性描述符可以精确的添加或者修改对象的属性。属性描述符需要使用 Object.defineProperty 来对属性进行添加或者修改。
Object.defineProperty
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
它可以接受三个参数
- 参数一:要定义属性的对象
- 参数二:要定义或修改的属性的名称或 Symbol;
- 参数三:要定义或修改的属性描述符
它的返回值
- 被传递给函数的对象
属性描述符分类
属性描述符分为数据属性以及存取属性。
数据描述符
数据描述符不可以有get
与set
。
configurable
表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性 描述符。
也就是说将该属性设置为false,则表明该属性不可删除,也不可能去再次配置。
不可删除案例
var obj = {
name : 'why',
age:18
}
Object.defineProperty(obj,"address",{
//很多配置
value:'北京',
configurable:false //该属性不可删除(还不可以去再次配置)
})
delete obj.address
console.log(obj.address); //输出北京
不可再次配置案例
var obj = {
name : 'why',
age:18
}
Object.defineProperty(obj,"address",{
value:'北京',
configurable:false //该属性不可删除(还不可以去再次配置)
})
Object.defineProperty(obj,"address",{
value:'南京',
configurable:true
})
console.log(obj.address); //报错
Enumerable
表示属性是否可以通过for-in或者Object.keys()返回该属性。也就是说表明该属性是否可被枚举。
不可枚举案例
var obj = {
name : 'why',
age:18
}
Object.defineProperty(obj,"address",{
value:'北京',
configurable:false,
enumerable:false,
})
console.log(obj); //没有北京
for(let value in obj){
console.log(value); //打印不了北京
}
writable
表示该属性是否可以被赋值(修改,写入)。
var obj = {
name : 'why',
age:18
}
Object.defineProperty(obj,"address",{
value:'北京',
configurable:false,
enumerable:false,
writable:false, //表示该属性是否可以被赋值(修改,写入)
})
obj.address = '上海'
console.log(obj.address); //还是北京
for(let value in obj){
console.log(value); //还是北京
}
数据描述符的默认值
var obj = {
name : 'why',
age:18
}
Object.defineProperty(obj,"address",{
value:'北京',
//假如不写 下面三个参数的默认值都是false
// configurable:false,
// enumerable:false,
// writable:false,
})
obj.address = '上海'
console.log(obj.address); //北京
delete obj.address
console.log(obj.address); //北京并没被删除
for(let value in obj){
console.log(value); //北京没有被打印出来
}
不使用属性修饰符的默认值
var obj = {
name : 'why',
age:18
}
obj.address = '上海'
// 下面三个参数都是true
// configurable:true,
// enumerable:true,
// writable:true,
存取属性描述符
属性描述符不可以有value
以及writable
。
什么时候用到呢?
- 隐藏真实属性,不希望被外界赋值与使用。
- 截获某一个属性它访问和设置值的过程。
var obj = {
name : 'why',
age:18,
_address:'北京' //隐藏真实属性
}
//什么时候用到呢
Object.defineProperty(obj,'address',{
//不可以有value
enumerable:true,
configurable:true,
get(){
foo()
return this._address
},
set(value){
bar()
this._address = value
},
})
obj.address = '上海'
console.log(obj.address);
function foo(){
console.log('获取一次address的值');
}
function bar(){
console.log('设置了一次address的值');
}
vue2响应式原理也是用到了存储属性修饰符。关于对源码的理解我也会在后续博文中更新。
转自本人掘金 https://juejin.cn/post/7106826860964626468/