Object.defineProperty用法
Object.defineProperty()
静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor)
参数:
obj:要定义属性的对象。
prop:一个字符串或 Symbol,指定了要定义或修改的属性键。
descriptor:要定义或修改的属性的描述符。
对象新增或者修改属性
let obj = {}
Object.defineProperty(obj, 'sex', {
value: 42
});
console.log(obj)
进行对象读取或写入值时的监听
let obj = {}
Object.defineProperty(obj, 'sex', {
get: function(val) { //访问对象属性时,触发get方法
console.log(obj)
obj.sex=2
return val
},
set: function(newVal) { //修改对象属性时,触发set方法
console.log('set:'+ newVal)
}
});
console.log(obj.sex)//访问对象属性
监听对象上的多个属性
监听对象需要,通过遍历对象的属性名进行Object.defineProperty绑定,从而实现对象属性的监听。
let obj = {
name: '',
sex: 0
}
// 实现一个响应式函数
function defineProperty(obj, key, val) {
Object.defineProperty(obj, key, {
get(val) {
console.log(`访问了${key}属性`)
return val
},
set(newVal) {
console.log(`${key}属性被修改为${newVal}了`)
val = newVal
}
})
}
// 实现一个遍历函数Observer
function Observer(obj) {
Object.keys(obj).forEach((key) => {
defineProperty(obj, key, obj[key])
})
}
Observer(obj)
console.log(obj.age)
obj.age = 18
console.log(obj.age)
Proxy用法
Proxy
是Es6的一个语法,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。new Proxy(target, handler)
var person = {
name: "张三"
};
var proxy = new Proxy(person, {
get: function(target, propKey) {
console.log(propKey+":"+target.name)//name:张三
},
set: function(obj, propKey, value) {
console.log(obj)//person的对象
console.log(propKey)//对象属性名
console.log(value)//对象属性值
}
});
proxy.name // "张三"
proxy.name ="小明"
proxy.sex="man"
proxy实现监听数据变化,传入目标target对象,不需要通过遍历属性就可以监听对象的变化。
Vue3响应式抛弃Object.defineProperty的原因
1.一次只能对一个属性进行监听,需要遍历来对所有属性监听。
- 在遇到一个对象的属性还是一个对象的情况下,需要递归监听。
- 对于对象的新增属性,需要手动监听
- 对于数组通过push、unshift方法增加的元素,也无法监听
网友评论