Proxyとは
これらは基本的な言語操作(例えば、プロパティ検索、代入、列挙、関数呼び出しなど)に割り込み、動作をカスタマイズできます。
メタプログラミングより
らしいです。自分の理解で説明すると、「プロパティ値に実際にアクセスする前にプロパティ値を好きに弄れる。元の値も返そうと思えば返せる」というような感じです。
Proxy Handler
new Proxy(obj, handler)
のように第2引数に渡します。ハンドラには特定のメソッドをいくつか作る必要があります。例えば、
値の取得時
get
値の設定時
set
in
構文でhas
関数実行時
apply
new
した時constructor
など。そしてこれらの事をトラップ(trap
)と言います。
Reflect について
Reflectを使うとgetter
やsetter
など関数の中のthis
をProxytarget
のように扱うことができます。
例
まずはget
とset
だけ見ていきます。
get
トラップ
const realObj = {
foo: 'foo',
get bar() {
return this._bar;
}
};
const handler = {
get(target, propName, receiver) {
if (target[propName]) {
return Reflect.get(...arguments);
}
return 'default value';
},
}
const obj = new Proxy(realObj, handler);
console.log(obj.foo, obj.bar); // 'foo' 'default value'
これはrealObj
にget
トラップを適用してます。obj.foo
の時はそのまま値が返りますが、obj.bar
の時はthis._bar
という値がないのでdefault value
が返ります。
set
トラップ
まずset
トラップは値を入れたか入れないかでboolean
を返すようにします。
const realObj = {
foo: 0,
_bar: 0,
set bar(value) {
this._bar = value;
},
set baz(value) {
this._baz = value;
}
};
const handler = {
set(target, propName, value, receiver) {
if (Object.prototype.hasOwnProperty.call(target, propName)) {
Reflect.set(...arguments);
return true;
}
return false;
},
}
const obj = new Proxy(realObj, handler);
obj.foo = obj.bar = obj.baz = 1;
console.log(obj.foo, obj._bar, obj._baz) // 1 1 undefined
これはfoo
と_bar
には1
が入りますが、_bar
は入りません。これはthis._baz
が無いためです。