プロキシとは
MDNのウェブサイトに記載されているように。
Proxyオブジェクトを使用すると、別のオブジェクトのプロキシを作成できます。これにより、そのオブジェクトの基本的な操作をインターセプトして再定義できます。
彼らがエージェントとは何かを説明するとき、彼らはそれがエージェントを作成できると言います**、それは少し面白いです。もちろん、それらは間違いではありませんが、このステートメントを単純化して、より親しみやすいものにすることができます。
_Proxy_オブジェクトを使用すると、ターゲットオブジェクトをラップできます。これにより、オブジェクトの基本的な操作をインターセプトして再定義できます。
基本的に、これは、オブジェクトをプロキシでラップする必要があることを意味します。これにより、「隠し」ドアを作成し、目的のオブジェクトへのすべてのアクセスを制御できます。
小さなエピソード、プロキシもソフトウェアデザインパターンです。読む必要があります(ウィキペディアのリンク)。
const target = {
message1: "hello",
message2: "everyone"
};
const handler = {};
const proxy = new Proxy(target, handler);
「エージェント」は2つのパラメータで作成されます。
- 「ターゲット」:ラップする元のオブジェクト(エージェント)。
- ハンドラー:インターセプトされる操作と、インターセプトされた操作のオブジェクトを再定義する方法を定義します。「トラップ」を呼び出すこともできます。
ほとんどのブラウザはプロキシをサポートしていますが、サポートしていない古いブラウザもあります(もちろん、IE)。ここで完全なリストを表示できます。Googleにはプロキシのポリフィルがありますが、すべてのプロキシ機能をサポートしているわけではありません。
プロキシとは何かがわかったので、それを使って何ができるかを確認したいと思います。
動作中のエージェント
私たちが銀行だと想像してみましょう。銀行口座の残高にアクセスして通知するたびに知りたいのです。最も単純なハンドラー操作/トラップを使用します。
上記の例では、私の名前と2020年の残高を持つ銀行口座オブジェクトがあります。
const bankAccount = {
balance: 2020,
name: 'Georgy Glezer'
};
const handler = {
get: function(target, prop, receiver) {
if (prop === 'balance') {
console.log(`Current Balance Of: ${target.name} Is: ${target.balance} `);
}
return target[prop];
}
};
const wrappedBankAcount = new Proxy(bankAccount, handler);
wrappedBankAcount.balance; // access to the balance
// OUTPUT:
// Current Balance Of: Georgy Glezer Is: 2020
// 2020
今回、ハンドラーオブジェクトはget操作/トラップを実装します。3つのパラメーターとgetの戻り値を持つ関数を受け取ります。
- ターゲット。訪問されているオブジェクト(カプセル化するオブジェクト)。
- prop:アクセスされているプロパティ。この例でアクセスされている属性は、「バランス」です。
- レシーバー:レシーバー。プロキシまたはプロキシから継承されたオブジェクトにすることができます。
条件を定義します。アクセスされている属性が "_balance" _の場合、残高と現在のユーザー名を通知(ログ)し、属性_ "balance" _を返します。
出力からわかるように、「balance」属性にアクセスすると、プロキシを使用してget操作/トラップを設定することでアクセスを簡単にログに記録できます。
私たちは引き続き銀行のアイデアを使用し、誰かが銀行口座からお金を引き出すたびに通知する必要があります。もう1つの制約は、銀行が負の残高を許可しないことです。これを実現するために、今回はセットハンドラー/トラップを使用します。
上記の例では、現在の残高と引き出し後の新しい残高を通知します。新しい残高がマイナスの場合は、引き出し操作も通知して中止します。
const bankAccount = {
balance: 2020,
name: 'Georgy Glezer'
};
const handler = {
set: function (obj, prop, value) {
console.log(`Current Balance: ${obj.balance}, New Balance: ${value}`);
if (value < 0) {
console.log(`We don't allow Negative Balance!`);
return false;
}
obj[prop] = value;
return true;
}
};
const wrappedBankAcount = new Proxy(bankAccount, handler);
wrappedBankAcount.balance -= 2000; // access to the balance
console.log(wrappedBankAcount.balance);
wrappedBankAcount.balance -= 50; // access to the balance
console.log(wrappedBankAcount.balance);
// OUTPUT:
// Current Balance: 2020, New Balance: 20
// 20
// Current Balance: 20, New Balance: -30
// We don't allow Negative Balance!
// 20
ブール値(true / false)を返す関数であるset operator / trapを使用して、更新操作が成功したかどうかを判別します。以下のパラメータを受け取ります。
- target:アクセスされているオブジェクト(カプセル化するオブジェクト)。
- prop:アクセスされているオブジェクト(カプセル化するオブジェクト)。この例では、アクセスされている属性は「バランス」です。
- 値。更新する必要がある新しい値。
- 受信者*:最初に割り当てられたオブジェクト。これは通常、エージェント自体です。ただし、set()ハンドラーは、プロトタイプチェーンまたはその他のさまざまなメソッドを介して間接的に呼び出すこともできます。
ご覧のとおり、実際にはgetと非常によく似ていますが、新しい値を持つ追加のパラメーターのみを受け取ります。
これらの2つの演算子/トラップが最も一般的です。既存のすべての演算子/トラップを見つけることに興味がある場合は、ここで確認できます。
プロキシを使用するのは誰か
多くの人気のあるライブラリは、この手法を使用しています。例:* [MobX]()
そしてもっと...それらのほとんどは、プロキシが私たちに与えた驚くべき力を利用し、私たちに素晴らしいライブラリを提供してくれました。
ユースケースと例
プロキシサーバーを使用してこれを行うことができることを確認しました。
- 記録(銀行に通知)
- 検証(マイナス残高の更新を防ぐ)
キャッシュ
get演算子/トラップを再度使用して、オブジェクトに「dollars」属性を追加します。「ドル」プロパティにアクセスするたびに、残高の価値を計算します。計算は重い操作なので、できるだけキャッシュしたいと思っています。
const bankAccount = {
balance: 10,
name: 'Georgy Glezer',
get dollars() {
console.log('Calculating Dollars');
return this.balance *3.43008459;
}
};
let cache = {
currentBalance: null,
currentValue: null
};
const handler = {
get: function (obj, prop) {
if (prop === 'dollars') {
let value = cache.currentBalance !== obj.balance ? obj[prop] : cache.currentValue;
cache.currentValue = value;
cache.currentBalance = obj.balance;
return value;
}
return obj[prop];
}
};
const wrappedBankAcount = new Proxy(bankAccount, handler);
console.log(wrappedBankAcount.dollars);
console.log(wrappedBankAcount.dollars);
console.log(wrappedBankAcount.dollars);
console.log(wrappedBankAcount.dollars);
// OUTPUT:
// Calculating Dollars
// 34.3008459
// 34.3008459
// 34.3008459
// 34.3008459
例でわかるように、現在の銀行の残高と残高の値を米ドルで保持するキャッシュオブジェクトがあります。誰かが「_dollars」_属性にアクセスするたびに、最初にそれを計算してからキャッシュします。
DOM操作
残高が変わるたびに画面上のテキストを更新したいと思います。集合演算子/トラップを使用し、値を変更するたびに、画面上のDOM要素を更新します。
const bankAccount = {
balance: 2020,
name: "Georgy Glezer",
get text() {
return `${this.name} Balance Is: ${this.balance}`;
}
};
const objectWithDom = (object, domId) => {
const handler = {
set: function (obj, prop, value) {
obj[prop] = value;
document.getElementById(domId).innerhtml = obj.text;
return true;
}
};
return new Proxy(object, handler);
};
// create a dom element with id: bank-account
const wrappedBankAccount = objectWithDom(bankAccount, "bank-account");
wrappedBankAccount.balance = 26;
wrappedBankAccount.balance = 100000;
ここでは、DOM要素のIDを格納し、集合演算子/トラップに単純な行を追加してDOM要素を更新できるように、ヘルパー関数を作成しました。簡単ですよね?
概要
要約すると、ECMAScript 6プロキシ、それらの使用方法、および目的を理解しています。私の意見では、プロキシは非常に素晴らしいツールです。これを使用してさまざまな選択を行うことができます。自分に最適なものを考えるだけで済みます:)。
元のテキストは次の場所から取得されます:https: //levelup.gitconnected.com/the-amazing-power-of- JavaScript -proxies-aa27c6d06bcb