源码
来自半年后的说明:我把代码转放到 gists 里了,当时代码风格受 Python 影响较大,这里就不再更改了,毕竟大家本地都有自己的格式化工具。
点击这里前往Github查看本文源码。
实现
我们要定义一个observer
函数,它会把我们传入的对象复制一份再进行代理,并且返回的代理对象上还有一个observe
方法,用来添加一个观察者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function observable(obj) { const observers = {} const target = Object.assign({ observe(key, fn) { observers[key] = fn 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。
使用
注意我们传给它的回调是接受两个参数,第一个表示旧值,第二个表示新值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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
ob.y = 20
|
读者可以打开控制台试一试效果。