🦭

Vueの学習をしていて新たに知ったProxyオブジェクトからJavaScriptの仕組みを考える

に公開

はじめに

現在,Vueフレームワークの仕組みについて学習をしていて,render の機能を作るところまで学習しました。次はVueの代表的な機能であるリアクティビティについての章なのですが,そこに出てきたProxy オブジェクトがおもしろかったので,そこからJavaScriptにDeep Diveしていきたいと思います。

Proxyオブジェクトとは

Proxy オブジェクトは,あるオブジェクトに対する操作を「代理」するための仕組みです。

const proxy = new Proxy(target, handler);

Proxy は 2つの要素から構成されます。

  • target
    実体となるオブジェクト
  • handler
    プロパティの取得や代入などの操作に介入するためのルール

Proxy を通してオブジェクトにアクセスすると,その操作は一度 handler を経由してから実行されます。
そのため,プロパティの参照や代入といった一見単純な操作に,独自の処理を割り込ませることができます。

ここで一つ疑問が生まれます。

なぜ,ただのプロパティ参照や代入に対して,Proxy のような仕組みで処理を割り込ませることができるのでしょうか。

JavaScriptはどうやってオブジェクトにアクセスしているのか

実は JavaScript では、オブジェクトのプロパティに直接アクセスしているわけではありません。

obj.x

このコード内部的には

obj.`[[Get]]`("x")

というふうに扱われます。
同様に

obj.x = 1

は

obj.`[[Set]]`("x", 1)

という内部メソッドの呼び出しに変換されます。

[[Get]] や [[Set]] は JavaScript エンジン内部にのみ存在する
「内部メソッド」と呼ばれる仕組みで、
JavaScript のコードから直接呼び出すことはできません。

しかし,プロパティの参照・代入・削除といった
あらゆるオブジェクト操作は必ずこれらの内部メソッドを経由して実行されます。

内部メソッドの詳細については,以下をご参照ください

Proxyでできること

前節で見たように、JavaScript では
プロパティの参照や代入といった操作が,必ず内部メソッドを経由して行われます。

Proxy は,この内部メソッドが呼び出されるタイミングに処理を挟むための仕組みです。

const proxy = new Proxy(target, {
  get(target, prop, receiver) {
    return Reflect.get(target, prop, receiver);
  },
  set(target, prop, value, receiver) {
    return Reflect.set(target, prop, value, receiver);
  }
});

このように Proxy を作成すると、

  • プロパティが参照されたとき
  • 値が代入されたとき

といったタイミングで、Proxy 側の処理が必ず実行されます。

重要なのは,コードの書き方は全く変わらないということです。

proxy.x
proxy.x = 1

これらは通常のオブジェクト操作と全く同じ構文ですが、
裏側では Proxy を経由した処理が動いています。

まとめ

Vueフレームワークの学習をきっかけにJavaScriptの理解を深めることができました。
現在私はフレームワークを作って学ぶThe chibivue Bookで学んでいます。興味のある方はぜひ参照ください。

Discussion