观察者模式
监听到对象的某个属性发生改变的时候,自动触发(执行)响应的函数。例如:vm.$watch(),vue的双向数据绑定
// 语法:Object.defineProperty(obj, prop, descriptor)
```javascript
// 显式
Object.defineProperty(obj, "key", {
enumerable: false, // 是否可枚举
configurable: false, // 是否可删除属性
writable: false, // 是否可修改属性
value: "static", // 属性的值
get() {
return value
},
set(newValue) {
value = newValue
}
})
// 拥有布尔值的键 configurable、enumerable 和 writable 的默认值都是 false。
// 属性值和函数的键 value、get 和 set 字段的默认值为 undefined。
// 定义待监听对象
const obj = {
name: 'zhangsan',
sayHi() {
console.log('hello')
}
}
Object.defineProperty(obj, name, {
get() {
return this.obj['name']
},
set() {
console.log('数据发生改变!')
this.obj.['name'] = 'lisi'
}
})
Proxy
Proxy/Reflect 是 ES6 引入的新特性, 也可以使用其完成观察者模式, 示例如下(效果和上面一样):
var obj = {
age: 20
}
var proxy = new Proxy(obj, {
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver)
}
})
proxy.age = 30 // 调用相应函数
// vue在3.0版本上使用 Proxy 对Object.defineProperty()重构的原因
// Object.defineProperty()的缺点:
// 1.不会监测到数组引用不变的操作(比如 push/pop 等)
// 2.只能监测到对象属性的改变, 即如果有深度嵌套的对象则需要再次给它绑定 Object.defineProperty()
// Proxy的优点
// 1.可以劫持数组的改变
// 2.defineProperty 是对属性的劫持, Proxy 是对对象的劫持