实现观察者模式

2022-10-24 16:33:17 浏览数 (3)

源码

点击这里前往Github查看本文源码。

实现

我们要定义一个observer函数,它会把我们传入的对象复制一份再进行代理,并且返回的代理对象上还有一个observe方法,用来添加一个观察者:

代码语言:javascript复制
function observable(obj) {
    const observers = {}
    
    // 使用Object.assign避免修改原对象
    const target = Object.assign({
        observe(key, fn) {
            observers[key] = fn
            // For method chaining
            return this
        }
    }, obj)

    const set = (target, key, value) => {
        const oldVal = Reflect.get(target, key)

        // 如果存在则调用当前属性对应的观察者回调函数,
        // 并且把它的旧值和新值传给回调函数
        observers[key]?.call(undefined, oldVal, value)
        
        return Reflect.set(target, key, value)
    }

    return new Proxy(target, { set })
}

其中我们使用了Object.assign来避免修改原对象,但是如果非要那么做也没什么大问题,只是容易出bug。

使用

注意我们传给它的回调是接受两个参数,第一个表示旧值,第二个表示新值:

代码语言:javascript复制
const ob = observable({
    x: 0,
    y: 1,
}).observe('x', (oldVal, newVal) => {
    console.log(`x: ${oldVal} -> ${newVal}`)
}).observe('y', (oldVal, newVal) => {
    console.log(`y: ${oldVal} -> ${newVal}`)
})

ob.x = 10
// x: 0 -> 10

ob.y = 20
// y: 1 -> 20

读者可以打开控制台试一试效果。

0 人点赞