如何js实现watch
实现数据监听(Watch)的方法
在JavaScript中实现类似Vue的watch功能,可以通过以下几种方式监听对象属性的变化:
使用Object.defineProperty
通过定义属性的getter/setter实现基础监听:

function observe(obj, key, callback) {
let value = obj[key]
Object.defineProperty(obj, key, {
get() {
return value
},
set(newVal) {
if (newVal !== value) {
const oldVal = value
value = newVal
callback(newVal, oldVal)
}
}
})
}
const data = { count: 0 }
observe(data, 'count', (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`)
})
使用Proxy实现深度监听
Proxy可以拦截整个对象的操作,适合深层监听:

function createWatcher(target, callback) {
return new Proxy(target, {
set(target, key, value, receiver) {
const oldValue = target[key]
if (oldValue !== value) {
Reflect.set(target, key, value, receiver)
callback(key, value, oldValue)
}
return true
}
})
}
const store = createWatcher({ price: 10 }, (key, newVal, oldVal) => {
console.log(`${key} updated: ${oldVal} -> ${newVal}`)
})
第三方库实现
使用现成的观察者模式库更高效:
// 使用MobX
import { observable, observe } from 'mobx'
const obj = observable({ value: 1 })
const disposer = observe(obj, change => {
console.log(`${change.name} changed`, change)
})
obj.value = 2
disposer() // 停止监听
自定义发布订阅模式
实现简单的观察者模式:
class Watcher {
constructor() {
this.subscribers = new Map()
}
watch(target, key, callback) {
if (!this.subscribers.has(target)) {
this.subscribers.set(target, new Map())
}
this.subscribers.get(target).set(key, callback)
}
notify(target, key, newVal, oldVal) {
const callbacks = this.subscribers.get(target)?.get(key)
callbacks?.(newVal, oldVal)
}
}
const watcher = new Watcher()
const obj = { data: '' }
watcher.watch(obj, 'data', (newVal) => console.log('Data changed:', newVal))
注意事项
- 原始方法无法检测数组变化,需特殊处理数组方法
- Proxy有更好的性能但存在浏览器兼容性问题
- 深层嵌套对象需要递归处理
- 考虑使用WeakMap避免内存泄漏






