序文
ES6では、プロキシコンストラクターはアクセス可能なグローバルオブジェクトであり、それを使用して、オブジェクトとさまざまな操作オブジェクトの動作の間の要求された操作に関するさまざまな情報を収集し、何をしたいのかを返すことができます。 ES6の矢印関数、配列の解体、RESTパラメーター、およびその他の機能は、実装されると広く流通していますが、プロキシなどの機能は開発者にはめったに見られません。一方では、ブラウザの互換性のためであり、一方では、これらの機能の利点があるため、開発者は使用シナリオを深く理解する必要があります。個人的には、ES6のプロキシが本当に好きです。なぜなら、簡潔で理解しやすい方法でオブジェクトへの外部アクセスを制御できるからです。以下では、最初にプロキシの使用方法を紹介し、次に特定の例をリストして、プロキシの使用シナリオを説明します。
プロキシは、名前と意味を参照して、デザインモードのプロキシモードと非常に類似した機能を持っています。これは、3つの側面でよく使用されます。
1.オブジェクトへの外部アクセスを監視します
2。関数またはクラスの複雑さ
3.操作の前に操作を確認するか、必要なリソースを管理する
プロキシをサポートするブラウザ環境では、プロキシは直接使用できるグローバルオブジェクトです。 Proxy(target, handler)はコンストラクターであり、 targetは起訴されたオブジェクトであり、 handlderさまざまなプロキシ操作を宣言するオブジェクトであり、最後にプロキシオブジェクトを返します。外の世界がプロキシオブジェクトを介してtargetオブジェクトのプロパティにアクセスするたびに、 handlerオブジェクトを通過します。このプロセスから、プロキシオブジェクトはミドルウェア(ミドルウェア)に非常に似ています。では、どのような操作がインターセプトできるのでしょうか?最も一般的な操作は、GET(読み取り)、セット(変更)オブジェクトプロパティなどです。インターセプタブル操作の完全なリストについては、ここをクリックしてください。さらに、プロキシオブジェクトは、すべてのプロキシ操作をいつでもログアウトできるrevokeメソッドも提供します。正式にプロキシを導入する前に、ES6に追加された新しいグローバルオブジェクトであるReflectを特定の理解を深めることをお勧めします。
基本
const target = {name: 'billy bob'、age:15}; const handler = {get(target、key、proxy){const today = new date(); console.log( `$ {key} at $ {today}`)のget request make ver {key} `); return Reflect.get(ターゲット、キー、プロキシ); }}; const proxy = new Proxy(ターゲット、ハンドラー); proxy.name; // => "2016年7月21日に名前を作成したリクエストを取得します15:26:20 gmt+0800(cst)" // => "Billy Bob" "上記のコードでは、最初にプロキシにされるtargetオブジェクトを定義し、次にすべてのプロキシ操作を含むhandlerオブジェクトを宣言します。次に、 Proxy(target, handler)を使用して、プロキシオブジェクトproxyを作成します。その後、 proxyを使用したtarget属性へのすべてのアクセスは、 handlerによって処理されます。
1。検証モジュールを終了します
単純なタイプの検証から始めましょう。これは、プロキシを使用してデータ型の精度を確保する方法を示しています。
numericdatastore = {count:0、rument:1234、total:14}; numericdatastore = new proxy(numericdatastore、{set(ターゲット、キー、値、プロキシ){if(typeof value!== 'number'){スローエラー( " }}); //「foo」がnumerdatastore.count = "foo"ではないためにエラーがスローされました。オブジェクトのすべてのプロパティに対して直接検証剤を開発したい場合、コード構造が肥大化し、プロキシを使用すると、検証剤をコアロジックから分離して1つに分けることができます。
function createValidator(target, validator) { return new Proxy(target, { _validator: validator, set(target, key, value, proxy) { if (target.hasOwnProperty(key)) { let validator = this._validator[key]; if (!!validator(value)) { return Reflect.set(target, key, value, proxy); } else { throw Error(`Cannot set $ {key} to $ {value} `); }、age(val){return typeof age == 'number' &&> 18; }} class person {constructor(name、age){this.name = name; this.age = age; return createvalidator(this、personvalidators); }} const bill = new person( 'bill'、25); //次の操作はエラーbill.name = 0; bill.age = 'bill'; bill.age = 15;チェッカーとメインロジックの分離を通じて、関連するクラスや機能に直接損傷を与えることなく、 personValidators検証剤のコンテンツを無限に拡張できます。より複雑にするために、プロキシを使用してタイプチェックをシミュレートして、関数が正しいタイプと量のパラメーターを受信するかどうかを確認することもできます。
obj = {pickymethodone:function(obj、str、num){ / *... * /}、pickymethodtwo:function(num、obj){ / *... * /}}; const argtypes = {pickymethodone:["object"、 "string"、 "number"]、pickymethodtwo: " {function、key、proxy){key]; function argchecker(name、args、checkers){for(var idx = 0; idx <args.length; idx ++){var arg = args [idx]; var type = Checkers [idx]; if(!arg || typeof arg!== type){console.warn( `$ {name}の署名を誤って実装しています。param$ {idx + 1}`); }}} obj.pickymethodone(); //> Pickymethodoneの署名を誤って実装しています。 PARAM 1 //を確認してください> Pickymethodoneの署名を誤って実装しています。 PARAM 2 //を確認してください> Pickymethodoneの署名を誤って実装しています。 param 3obj.pickymethodtwo( "wopdapodoo"、{})を確認してください。 //> Pickymethodoneの署名を誤って実装しています。 param 3obj.pickymethodtwo( "wopdapodoo"、{})を確認してください。 //> Pickymethodoneの署名を誤って実装しています。 param 3obj.pickymethodtwo( "wopdapodoo"、{})を確認してください。 //> Pickymethodtwoの署名を誤って実装しています。 PARAM 1 //警告なしloggedobj.pickymethodone({}、 "a Little String"、123); obj.pickymethodone(123、{});2。プライベート属性
JavaScriptまたはその他の言語では、変数名の前に_を追加して、これが私有財産であることを示すことが慣習です(実際にはプライベートではありません)が、誰もアクセスまたは変更しないことを保証することはできません。次のコードでは、 apiオブジェクト内のメソッド呼び出しを容易にするためにプライベートapiKeyを宣言しますが、外側からapi._apiKeyにアクセスすることはできません。
var api = {_apikey: '123abc456def'、/ * this._apikey */ getusers:function(){}、getuser:function(userid){}、setuser:function(userid、config){}}; // logs 'logs' private '; api._apikey); //希望のように_apikeyをget and mutate _apikey = api._apikey; api._apikey = '987654321';明らかに、条約は抑制されていません。 ES6プロキシを使用して、実際のプライベート変数を実装できます。以下は、異なる読書方法の2つの異なるプライベートメソッドを示しています。
最初の方法は、セット/取得を使用して読み取りおよび書き込みリクエストをインターセプトし、 undefined:
let api = {_apikey: '123abc456def'、getusers:function(){}、getuser:function(userid){}、setuser:function(userid、config){}}; > -1){`$ {key}は制限されていますrefrect.get(ターゲット、キー、値、プロキシ);2番目の方法は、使用中のインターセプトを使用することです。
var api = {_apikey: '123abc456def'、getusers:function(){}、getuser:function(userid){}、const restrented = ['_apikey']; false:refric.has(key);プロキシは_apikey ... ")}}3。アクセスログ
頻繁に呼び出したり、ゆっくりと実行したり、実行環境でより多くのリソースを取り上げる属性またはインターフェイスについては、開発者は使用またはパフォーマンスを記録したいと思うでしょう。現時点では、プロキシを使用してミドルウェアとして機能し、ロギング関数を簡単に実装できます。
let api = {_apikey: '123abc456def'、getusers:function(){ / * ... * /}、getuser:function(userid){ / * ... * /}、setuser:function(userid、config){ / * ... * /}}; function logmethasync(settime、settimeout() console.log( `$ {timestamp} - $ {method} request asynchronally.`)、0)} api = new proxy({get:key、key、proxy){var value =ターゲット[key]; return function(... argument) }; api.getusers();4。早期警告と傍受
他の開発者にnoDelete属性を削除することを望まないとし、 oldMethodに電話する開発者にこの方法が放棄されたことを理解してもらいたい、または開発者にdoNotChange属性を変更しないように指示してもらいたいとします。
let dataStore = {nodelete:1235、oldmethod:function(){/*.../}、donotchange: "red and true"}; const nodelete = ['nodelete']; const nochange = ['donotchange']; const deprecated = ['oldmethod']; DataStore = new Proxy(dataStore、{set(ターゲット、キー、値、プロキシ){if(nochange.includes(key)){shrow error( `error!$ {key}は不変です。`);} return.set(ターゲット、キー、値、プロキシ);エラー($ {key}は削除できません。 function(... riffer.apply(ターゲット]、ターゲット、args); DataStore.Nodeleteを削除します。 datastore.oldmethod();5。フィルター操作
一部の操作は、大きなファイルの転送など、リソースを非常に取り上げます。現時点では、ファイルがすでにチャンクで送信されている場合、新しいリクエストに対応する(非曖昧)を作成する必要はありません。現時点では、プロキシを使用してリクエストの機能を検出し、応答する必要がないものと機能に応じて応答する必要があるものを除外できます。次のコードは、完全なコードではなく、機能をフィルタリングする方法を簡単に示します。私は誰もが素晴らしいことを理解すると信じています:
let obj = {getgiantFile:function(fileid){/*...*/}}; obj = new proxy(obj、{get(target、key、proxy){return function(... args){const ids [0]; (ISENROUTE || ISDOWNロード){cached){return cached(ターゲット、ターゲット、}});6。割り込みエージェント
Proxyは、ターゲットにターゲットをtargetにサポートします。これは、データまたはインターフェイスへのアクセスを完全に囲むためによく使用されます。次の例では、 Proxy.revocable Methodを使用して、次のようなプロキシオブジェクトを作成しました。
sensitivedata = {username: 'devbryce'}; const {sensitivedata、revokeaccess} = proxy.revocable(sensitivedata、handler); function handlesuspectedhack(){revokecass();} // logs 'devbryconsole.logivedata.usata. handLesuspectedHack(); // typeRerr:regokedConsole.log(sensitivedata.username);デコレーター
ES7で実装されたデコレーターは、設計モードのデコレーターモードと同等です。プロキシとデコレーターの使用シナリオを単に区別するだけで、それは次のように要約できます。プロキシのコア機能は、外部の世界のエージェントへのアクセスを制御することであり、デコレーターのコア機能は装飾器の機能を強化することです。コアの使用シナリオ、アクセスログなどの機能に大きな違いをもたらす限り、この記事ではプロキシ実装を使用していますが、デコレーターを使用して実装することもできます。開発者は、プロジェクトのニーズ、チームの仕様、および独自の好みに基づいて自由に選択できます。
要約します
ES6のプロキシはまだ非常に実用的です。一見シンプルな機能は非常に有用です。 ES6を学ぶのが誰でも役立つことを願っています。