javascript入門
What is a JavaScript proxy? you might ask. It is one of the features that shipped with ES6. Sadly, it seems not to be widely used.
什么是JavaScript代理? 你可能會問。 這是ES6附帶的功能之一。 可悲的是,它似乎并未得到廣泛使用。
According to the MDN Web Docs:
根據MDN網絡文檔 :
The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).
Proxy對象用于定義基本操作的自定義行為(例如,屬性查找,賦值,枚舉,函數調用等)。
In simple terms, proxies are getters and setters with lots of swag. A proxy object sits between an object and the outside world. They intercept calls to the attributes and methods of an object even if those attributes and methods don’t exist.
簡單來說,代理是getter和setter方法有很多贓物。 代理對象位于對象和外界之間。 即使對象屬性和方法不存在,它們也會攔截對它們的調用。
For us to understand how proxies work, we need to define three terms used by proxies:
為了讓我們理解代理的工作方式,我們需要定義代理使用的三個術語:
handler: The placeholder object which contains traps (they’re the interceptors).
handler :包含陷阱的占位符對象(它們是攔截器)。
traps: The methods that provide property access (they live inside the handler).
traps :提供屬性訪問的方法(它們位于處理程序內部)。
target: The object which the proxy virtualizes.
target :代理虛擬化的對象。
句法 (Syntax)
let myProxy = new Proxy(target, handler);
為什么要代理? (Why proxies?)
Since proxies are similar to getters and setters, why should we use them? Let’s see why:
由于代理類似于getter和setter,我們為什么要使用它們? 讓我們看看為什么:
const staff = {_name: "Jane Doe",_age: 25,get name() {console.log(this._name);},get age() {console.log(this._age);},set age(newAge) {this._age = newAge;console.log(this._age)}
};
staff.name // => "Jane Doe"
staff.age // => 25
staff.age = 30
staff.age // => 30
staff.position // => undefined
Let’s write the same code with proxies:
讓我們用代理編寫相同的代碼:
const staff = {name: "Jane Doe",age: 25
}
const handler = {get: (target, name) => {name in target ? console.log(target[name]) : console.log('404 not found');},set: (target, name, value) => {target[name] = value;}
}
const staffProxy = new Proxy(staff, handler);
staffProxy.name // => "Jane Doe"
staffProxy.age // => 25
staffProxy.age = 30
staffProxy.age // => 30
staffProxy.position // => '404 not found'
In the above example using getters and setters, we have to define a getter and setter for each attribute in the staff
object. When we try to access a non-existing property, we get undefined
.
在上面的使用getter和setter的示例中,我們必須為staff
對象中的每個屬性定義一個getter和setter 。 當我們嘗試訪問不存在的屬性時,我們得到undefined
。
With proxies, we only need one get
and set
trap to manage interactions with every property in the staff
object. Whenever we try to access a non-existing property, we get a custom error message.
使用代理,我們只需要一個get
and set
陷阱即可管理與staff
對象中每個屬性的交互。 每當我們嘗試訪問不存在的屬性時,都會收到自定義錯誤消息。
There are many other use cases for proxies. Let’s explore some:
代理還有許多其他用例。 讓我們探索一些:
代理驗證 (Validation with proxies)
With proxies, we can enforce value validations in JavaScript objects. Let’s say we have a staff
schema and would like to perform some validations before a staff can be saved:
使用代理,我們可以在JavaScript對象中強制執行值驗證。 假設我們有一個staff
模式,并且希望在保存職員之前執行一些驗證:
const validator = {set: (target, key, value) => {const allowedProperties = ['name', 'age', 'position'];if (!allowedProperties.includes(key)) {throw new Error(`${key} is not a valid property`)}if (key === 'age') {if (typeof value !== 'number' || Number.isNaN(value) || value <= 0) {throw new TypeError('Age must be a positive number')}}if (key === 'name' || key === 'position') {if (typeof value !== 'string' || value.length <= 0) {throw new TypeError(`${key} must be a valid string`)}}target[key] = value; // save the valuereturn true; // indicate success}
}
const staff = new Proxy({}, validator);
staff.stats = "malicious code" //=> Uncaught Error: stats is not a valid property
staff.age = 0 //=> Uncaught TypeError: Age must be a positive number
staff.age = 10
staff.age //=> 10
staff.name = '' //=> Uncaught TypeError: name must be a valid string
In the code snippet above, we declare a validator
handler where we have an array of allowedProperties
. In the set
trap, we check if the key being set is part of our allowedProperties
. If it’s not, we throw an error. We also check if the values being set are of certain data types before we save the value.
在上面的代碼片段中,我們聲明了一個validator
處理程序,其中有一個allowedProperties
數組。 在set
陷阱中,我們檢查設置的鍵是否是我們allowedProperties
一部分。 如果不是,則拋出錯誤。 在保存值之前,我們還檢查設置的值是否屬于某些數據類型。
可撤銷代理 (Revocable proxies)
What if we wanted to revoke access to an object? Well, JavaScript proxies have a Proxy.revocable()
method which creates a revocable proxy. This gives us the ability to revoke access to a proxy. Let’s see how it works:
如果我們想撤消對某個對象的訪問該怎么辦? 嗯,JavaScript代理具有Proxy.revocable()
方法,該方法創建可撤消的代理。 這使我們能夠撤消對代理的訪問。 讓我們看看它是如何工作的:
const handler = {get: (target, name) => {name in target ? console.log(target[name]) : console.log('404 not found');console.log(target)},set: (target, name, value) => {target[name] = value;}
}
const staff = {name: "Jane Doe",age: 25
}
let { proxy, revoke } = Proxy.revocable(staff, handler);
proxy.age // => 25
proxy.name // => "Jane Doe"
proxy.age = 30
proxy.age // => 30
revoke() // revoke access to the proxy
proxy.age // => Uncaught TypeError: Cannot perform 'get' on a proxy that has been revoked
proxy.age = 30 // => Uncaught TypeError: Cannot perform 'set' on a proxy that has been revoked
In the example above, we are using destructuring to access theproxy
and revoke
properties of the object returned by Proxy.revocable()
.
在上面的示例中,我們使用解構來訪問proxy
并revoke
Proxy.revocable()
返回的對象的屬性。
After we call the revoke
function, any operation applied to proxy
causes a TypeError
. With this in our code, we can prevent users from taking certain actions on certain objects.
調用revoke
函數后,應用于proxy
任何操作都會導致TypeError
。 使用此代碼,我們可以防止用戶對某些對象執行某些操作。
JavaScript proxies are a powerful way to create and manage interactions between objects. Other real world applications for Proxies include:
JavaScript代理是創建和管理對象之間的交互的強大方法。 代理的其他實際應用程序包括:
- Extending constructors 擴展構造函數
- Manipulating DOM nodes 操作DOM節點
- Value correction and an extra property 價值校正和額外的屬性
- Tracing property accesses 跟蹤屬性訪問
- Trapping function calls 陷阱函數調用
And the list goes on.
而這樣的例子不勝枚舉。
There’s more to proxies than we have covered here. You can check the Proxy MDN Docs to find out all the available traps and how to use them.
代理比我們在這里討論的更多。 您可以檢查“ 代理MDN文檔”以找到所有可用的陷阱以及如何使用它們。
I hope you found this tutorial useful. Please do and share so others can find this article. Hit me up on Twitter @developia_ with questions or for a chat.
希望本教程對您有所幫助。 請分享,以便其他人可以找到本文。 通過問題或聊天在Twitter @d evelopia_上打我。
翻譯自: https://www.freecodecamp.org/news/a-quick-intro-to-javascript-proxies-55695ddc4f98/
javascript入門