最近在学习vue的过程中,经常看见vue的响应式原理这一概念,经过查询是基于Object.defineProperty这一API,现在和大家分享一下我的学习笔记:
####1.基础语法
Object.defineProperty(obj, prop, descriptor)
作用:直接在对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
####2.参数
-
obj : 必需,目标对象。
-
prop : 必需,要定义或修改的属性名
-
descriptor:必需,要定义或修改的属性描述符对象
####3.descriptor(分为数据描述符和存取描述符)
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。
3.1两种描述符公用的属性
1.enumerable
当且仅当该属性的 enumerable
键值为 true
时,该属性才会出现在对象的枚举(for-in
或Object.keys( )
)属性中,设置为false
不可以被循环。默认值为false
。
Object.defineProperty(obj,'age',{
value:18,
writable:true,
enumerable:true
})
for(let key in obj){
console.log(key);//name age
}
2.configurable
当且仅当该属性的 configurable
键值为 true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false
。
Object.defineProperty(obj,'age',{
value:18,
writable:true,
enumerable:true,
configurable:true
})
delete obj.age
console.log(obj);//{name: 'zs'}
3.2数据描述符
1. value
该属性对应的值可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined
。
let obj ={
name:'zs',
}
//value: 被定义的属性的值,不写默认undefined
Object.defineProperty(obj,'age',{
value:18
})
console.log(obj);//{name: 'zs', age: undefined}
2. writable
该属性对应的值是布尔值,当且仅当 writable
值为 true
时,value
的值,才能被赋值运算符改变。 默认为 false
Object.defineProperty(obj,'age',{
value:18,
writable:true
})
obj.age = 20;//值为true时赋值生效
3.3存取描述符
1.getter函数
访问该属性prop
时,getter
函数会被执行。函数的返回值作为该属性的值返回
2.setter函数
当属性值被修改时,该方法会被执行。接受一个唯一参数,这个参数就是被赋的新值
存取的实现思路:通过在Object.defineProperty外部保存一个值,让setter函数被执行时,将修改的新值赋值给外部保存的initValue
,再通过getter函数将initValue
返回赋值给prop
注意:不要在函数内部做同样的事情(setter内设置值,getter内获取值),否则会导致栈溢出
let obj ={
name:'zs',
}
let initValue = 18 //外部保存一个值
Object.defineProperty(obj,'age',{
enumerable:true,
configurable:true,
get:function(){
console.log('getter方法被调用了');
// return obj.age //会导致栈溢出
return initValue
},
set:function(value){
console.log('setter方法的新值是' + value);
// obj.age = value //会导致栈溢出
initValue = value
}
})