コフス技術ブログ

JavaScriptファイル間でプロパティの変化をウォッチする手段

たとえばデータバインディングが気軽に利用できない環境、Reduxなどの状態管理ライブラリの導入ができない環境で、プロパティの変化に応じたリアクティブな処理を行いたい時はObject.definePropertyを使ってみるのも1つの手です。

以下にindex.tsを用意しました。
ページ読み込み後、任意のタイミングでwindowオブジェクトのisActiveの値を変更する処理を行います。

index.ts
import './pages/watch'

declare global {
  interface Window { [key: string]: boolean }
}

const loaded = () => {
  setTimeout(() => (window.isActive = true), 2500)
  setTimeout(() => (window.isActive = false), 5000)
}

window.addEventListener('load', loaded)

この時、./pages/watch.ts内でwindow.isActiveの値の変化は以下でウォッチできます。

./pages/watch.ts
const watchProp = (obj: Window, propName: string): void => {
  let value = obj[propName]
  Object.defineProperty(obj, propName, {
    get: () => value,
    set: newValue => {
      value = newValue

      if (value) console.log('isActive is true')

      if (!value) console.log('isActive is false')
    }
  })
}

watchProp(window, 'isActive')

上記例を実行した結果が以下です。

00:30:00.359 watch.ts:9  isActive is true
00:30:02.859 watch.ts:11 isActive is false

変化したタイミングで任意の処理を行うことができるので、とくにネイティブなJavaScriptにおいてファイルを跨いだプロパティの変化に応じたリアクティブな処理を行いたい場合に活用できそうです。

参考:MDN - Object.defineProperty()
参考:https://qiita.com/yamamo_yamayama/items/0dac5b4a6e5fcc8a3207