blog

プロキシ - オブジェクトにインターセプトのレイヤーを追加する

プロキシはブローカーとして動作し、外部からのオブジェクトへのアクセスは、まずこのブローカーによってインターセプトされなければなりません。 つまり、プロキシを動作させるには、対象のオブジェクトではなく、...

Apr 7, 2020 · 4 min. read
シェア

Proxyに関連する概念

プロキシは、特定の操作のデフォルトの動作を変更するために使用されます。

別の言い方をすれば あなたが作ったオブジェクトは大きな星で、プロキシはその大きな星のエージェントだと考えてほしい。, さて、広告主はこの大スターを見つけたいので、広告主はまずブローカーに行かなければならない!, 広告主が誠実でないとエージェントが思えば、広告主を拒否すればいい。

プロキシはこのブローカーとして働き、外部からのこのオブジェクトへのアクセスは、まずこのインターセプトを通らなければなりません。

もちろん、広告主はブローカーを通さずに直接このビッグスターを見つけるのだろうか、と言われるかもしれないが、このような状況も存在する。
つまり、この場合、ブローカーもインターセプトもフィルタリングもない。

つまり、プロキシが機能するためには、操作はターゲットオブジェクト上ではなく、プロキシインスタンス上で実行されなければなりません。

さて、プロキシについて少しわかったところで、プロキシの使い方を見てみましょう。

ES6ではProxyインスタンスを生成するためにProxyコンストラクタが用意されています。

const proxy = new Proxy(target,handler) targetつまり、ターゲットオブジェクト, handlerこれは、インターセプトの振る舞いをカスタマイズするために使用できる。

豆知識

tips: 1:ハンドラにインターセプターが設定されていない場合は、ターゲットオブジェクトに直接フォールされ、前と同じように結果を生成する。 ((例えば、ブローカーが報酬を得ても何もせず、すべてを大スターに投げてしまうような場合)。 2もちろん、ブローカーは指定されたことは何でもする。 3プロキシのインスタンスは他のオブジェクトのプロトタイプになることもできる。 const proxy = new Proxy({},{ get:function(target,propKey){ return 35; } }) let obj = Object.create(proxy); obj.time //35 ここでは、プロキシをプロトタイプとするオブジェクトを作成している。, そして、プロトタイプチェーンでそれを探し、彼のプロトタイプはプロキシであり、プロキシがこのプロパティを読み込むと、インターセプトされ、35を返す。

操作の種類

もちろん、ブローカーは全能ではありませんし、必ずしもすべてを知っているわけではありません。

1これは 元のオブジェクトにバインドすることで解決できる:
	プロキシのようなオブジェクトプロパティの読み込みをインターセプトする.fooとプロキシ['foo'] 
2これは 元のオブジェクトにバインドすることで解決できる:
	プロキシのようなオブジェクトのプロパティの設定をインターセプトする.foo = vまたはプロキシ['foo'] = v,ブール値を返す 
3これは、元のオブジェクトにバインドすることで解決できる:
	プロキシでpropKeyの操作をインターセプトし、ブール値を返す 
4これは、元のオブジェクトにバインドすることで解決できる:deleteProperty:
	削除プロキシを拒否する[propKey]操作はブール値を返す。
5これは、元のオブジェクト:ownKeysにバインドすることで解決できる:
	オブジェクトをインターセプトする.getOwnPropertyNames(proxy)オブジェクト.getOwnPropertySymbols(proxy)、
 Object.keys(proxy)これは元のオブジェクトにバインドすることで解決できる。...inループで配列を返す。このメソッドは、ターゲットオブジェクト自身のすべてのプロパティのプロパティ名を返す,
 オブジェクト.keys()プロキシの返される結果には、ターゲットオブジェクト自身のトラバース可能なプロパティのみが含まれる。
6これは、元のオブジェクトにバインドすることで解決できる: getOwnPropertyDescriptor:
	オブジェクトをインターセプトする.getOwnPropertyDescriptor(proxy, propKey),プロパティの説明を返す。
7defineProperty:
	オブジェクトをインターセプトする.defineProperty(proxy, propKey, propDesc)、
 Object.defineProperties(proxy, propDescs),ブール値を返す。
8: preventExtensions:
	オブジェクトをインターセプトする.preventExtensions(proxy),ブール値を返す。
9これは、元のオブジェクトにバインドすることで解決できる:getPrototypeOf:
	オブジェクトをインターセプトする.getPrototypeOf(proxy),オブジェクトを返す。
10: isExtensible:
	オブジェクトをインターセプトする.isExtensible(proxy),ブール値を返す。
11: setPrototypeOf:
	オブジェクトをインターセプトする.setPrototypeOf(proxy, proto),ブール値を返す。ターゲットオブジェクトが関数の場合、インターセプトできる操作が2つ追加される。
12これは、元のオブジェクトにバインドすることで解決できる:
	Proxyインスタンスの操作を関数呼び出しとしてインターセプトする。...args)これは、元のオブジェクトにバインドすることで行う。.call(object, ...args)これは、元のオブジェクトにバインドすることで行う。.apply(...)。
13これは、元のオブジェクトにバインドすることで解決できる:
	Proxyインスタンスがコンストラクタとして呼び出される操作、例えば newproxy(...args)。

詳細はご覧ください。

大スターが代理人をクビにしたいとき、どうすればいいんですか?

Proxy.revocable() ---プロキシの解除

Proxy.revocable()メソッドは、キャンセル可能なProxyのインスタンスを返します。

例を挙げる:
	const target = {};
 const handler = {};
 const {proxy,revoke} = Proxy.revocable(target,handler);
 proxy.foo = 123;
 proxy.foo //123
 revoke();
 proxy.foo // TypeError:Revoke
 
  
 Proxy.revocableこのメソッドは、proxy属性がプロキシインスタンスで、revoke()属性が関数であるオブジェクトを返す。
 プロキシのインスタンスはキャンセルできる。
 そのため、revoke関数を実行した後にプロキシインスタンスにアクセスすると、エラーが報告される。

This

Proxyはターゲット・オブジェクトに対するアクセスをプロキシすることはできますが、ターゲット・オブジェクトの透過的なプロキシではありません。

その主な理由は、ターゲット・オブジェクト内の thisキーワードがプロキシを指しているからです。

例を挙げる: const target = { m:function (){ console.log(this === proxy) } } const handler = {}; const proxy = new Proxy(target,handler) target.m() //false proxy.m() // true ここでは、プロキシはターゲット.m,後者の内部 thisは、ターゲットではなくプロキシを指している。

また、ネイティブ・オブジェクトの内部プロパティには、適切な thisでなければ取得できないものもあります。

そのため、プロキシはこれらのネイティブオブジェクトのプロパティをプロキシすることはできませんが、元のオブジェクトにバインドすることでこれを回避することができます。

Read next

分割、バックトラック、BFS&DFS、貪欲、二分探索

分割、バックトラック ◉ 要素の多数決 ◉ ブラケット生成問題 ◉ 島の数 ◉ pow ◉ substrの部分集合 ◉ 多要素 ◉ 電話番号の組み合わせ ◉ NqueenBFS&DFS ◉ 2分木の階層的走査 ◉ 最小遺伝子変化 ◉ ブラケット生成

Apr 7, 2020 · 3 min read