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入门