【JSリファレンス】Proxyコンストラクター

更新日:2024/06/14

Proxyコンストラクターは、プロパティへの代入操作や値の取得、関数の実行等を検知し、独自の処理を行う仕組みを提供するProxyオブジェクト生成します。

オブジェクトは内部スロットという、プログラムコードからアクセスできないプロパティを複数所持しています。
この内部スロットは、プロパティへの代入や値取得を行う時に呼び出されるメソッドが定義されています。

基本的にオブジェクトの内部スロットは、同じ処理が定義されています。

Proxyオブジェクトは例外として独自の動作が定義されており、プログラムコードで記述したメソッドを実行できるようになっています。

 

■Proxyオブジェクトの仕組み

Proxyコンストラクター任意のオブジェクト(対象オブジェクト)ハンドラーオブジェクトを引数として受け取り、Proxyオブジェクトを生成します。
ハンドラーオブジェクトは、介入する内部スロットと介入時に呼び出す関数が記述されています。

生成されたProxyオブジェクトの内部スロットが呼び出されると、対応するハンドラーがハンドラーオブジェクトに定義されているかどうかがチェックされます。

定義されていなかった場合、対象オブジェクトの内部スロットが呼び出され、その結果がそのままProxyの内部スロットの実行結果になります。

ハンドラーが定義されていた場合は、そのハンドラー関数が呼び出されます。
ハンドラー関数内で、対象オブジェクトの内部スロットを呼び出すかどうかは、その関数次第です。
ただし何らかの値を返す必要があります。
ハンドラー関数の戻り値は妥当性の検証が行われ、場合によっては TypeErrorがスローされます。

内部スロットの実行結果は呼び出し元によって、チェックされる場合があります。
そのため内部スロットでエラーにならない場合でも、呼び出し元でエラー判定される可能性があります。

 

■対象内部スロットとハンドラーオブジェクト

ハンドラーオブジェクトは、内部スロットに対応するハンドラー名をプロパティ名として定義します。
内部スロットとハンドラー名の対応は、次表のようになっています。

呼び出される関数については、ハンドラー名のリンク先を参照してください。

内部スロットハンドラー名
(プロパティ名)
意味
[[Call]]apply関数を実行する
[[Construct]]constructインスタンスを生成する
[[DefineOwnProperty]]definePropertyプロパティを作成または変更する
[[Delete]]deletePropertyプロパティを削除する
[[Get]]getプロパティの値を得る
[[GetOwnProperty]]getOwnPropertyDescriptorプロパティ記述子を得る
[[GetPrototypeOf]]getPrototypeOfプロトタイプを得る
[[HasProperty]]hasプロパティを所持しているかどうかを得る
(プロトタイプチェーン含む)
[[IsExtensible]]isExtensibleオブジェクトにプロパティ
を追加可能かどうかを得る
[[OwnPropertyKeys]]ownKeysプロパティ名のリストを得る
(プロトタイプチェーン含まない)
[[PreventExtensions]]preventExtensionsオブジェクトのプロパティ追加を不可にする
[[Set]]setプロパティに値をセットする
[[SetPrototypeOf]]setPrototypeOfプロトタイプをセットする

 

■使用例

  // 対象オブジェクト
const obj = {
    v:100
}
  // ハンドラーオブジェクト [[Set]]のみ定義
const handlerObj = {
    set:function(obj, propName, value){
          // 数値のみセット可能
        if( typeof value !== "number" ) return false;
          // 対象オブジェクトの [[Set]] を呼び出す
        return Reflect.set( obj, propName, value );
    }
}
  // Proxyオブジェクトの生成
const proxyObj = new Proxy( obj ,handlerObj );

  // 数値のセット
proxyObj.v = 200;
console.log( proxyObj.v , obj.v);
// 結果:  200 200

  // 文字列のセット ※無効
proxyObj.v = "hello!";
console.log( proxyObj.v , obj.v);
// 結果:  200 200

  // 対象オブジェクトを直接変更
obj.v = "hello!";
console.log( proxyObj.v , obj.v);
// 結果:  hello! hello!

Reflectについては、Reflectオブジェクトを参照してください。

 

■コンストラクター

 

■プロパティ

 

■メソッド

 

関連ページ

更新日:2024/06/14

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://jsref.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。