当前位置:首页 > JavaScript

如何js实现watch

2026-02-03 08:22:00JavaScript

实现数据监听(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() // 停止监听

自定义发布订阅模式

实现简单的观察者模式:

如何js实现watch

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避免内存泄漏

标签: jswatch
分享给朋友:

相关文章

js实现跳转

js实现跳转

使用 window.location 跳转 通过修改 window.location.href 或直接使用 window.location 实现页面跳转,适用于普通跳转或带参数的 URL。 // 方…

vue实现js休眠

vue实现js休眠

Vue 中实现 JavaScript 休眠 在 Vue 中实现 JavaScript 休眠通常需要使用异步方式,以避免阻塞主线程。以下是几种常见方法: 使用 setTimeout 和 Promise…

js实现求导

js实现求导

实现数值求导的方法 在JavaScript中实现求导通常采用数值方法,因为JavaScript不是符号计算语言。以下是常见的数值微分方法: 中心差分法 中心差分法提供较高精度的导数近似:…

js实现文字滚动

js实现文字滚动

实现文字滚动的几种方法 使用CSS动画实现滚动 通过CSS的@keyframes和transform属性可以实现平滑的文字滚动效果。 <style> .scroll-text { w…

js实现下拉菜单

js实现下拉菜单

使用HTML和CSS创建基础结构 HTML部分需要包含一个触发下拉的按钮和隐藏的下拉菜单内容: <div class="dropdown"> <button class="dr…

js实现路由

js实现路由

js实现路由的方法 在JavaScript中实现路由功能可以通过多种方式完成,以下是几种常见的方法: 使用原生JavaScript实现路由 通过监听window.onhashchange事件来实现基…