Javascript 简明教程
JavaScript - Proxies
Proxy in JavaScript
JavaScript proxies 是允许你包装特定对象和自定义对象的基本操作(如获取和设置对象属性)的对象。简而言之,使用该代理对象,你可以向对象添加自定义行为。代理用于实现诸如日志记录、缓存和安全之类的功能。
我们可以使用 JavaScript 中的 Proxy() 构造函数创建代理对象。该构造函数接受两个参数——目标对象和处理程序对象。它为目标对象返回一个新的代理对象。
Syntax
以下是 JavaScript 中创建代理对象的语法——
const obj = new Proxy(targetObj, Handler);
我们在上述语法中使用带有 new 关键字的 Proxy() 构造函数。
Parameters
Proxy 构造函数采用两个参数。
-
targetObj − 这是您想要为其创建代理对象并自定义其默认行为的目标对象。
-
Handler − 这是包含自定义目标对象行为的功能的对象。
Example
在下面的示例中,person 对象包含 name 和 age 属性。
我们为名为 proxyObj 的 person 对象定义了代理对象。此外,我们还将处理程序对象作为 Proxy() 构造函数参数传递。
在处理程序对象中,我们定义了访问对象属性的 getter。getter 检查对象是否包含您要查找的属性。如果是,它将返回属性值。否则,它将返回消息,说明对象不包含该属性。
<html>
<body>
<div id = "demo1">The name of the person is: </div>
<div id = "demo2">The height of the person is: </div>
<script>
const person = {
name: "Same",
age: 32,
}
const handler = {
// Defining the getters
get: function (object, property) {
return object[property] ? object[property] :
'Object doesnt contain the property.';
}
}
const proxyObj = new Proxy(person, handler);
document.getElementById("demo1").innerHTML += proxyObj.name;
document.getElementById("demo2").innerHTML += proxyObj.height;
</script>
</body>
</html>
The name of the person is: Same
The height of the person is: Object doesnt contain the property.
当您从对象访问不存在的属性时,它会返回 undefined。这里,我们自定义了对象的默认行为来返回一种简洁而可读的方法。
JavaScript Proxy Handlers
JavaScript 中有多个代理处理程序可用,我们将在下面涵盖其中一些内容。代理处理程序用于覆盖对象的默认行为。
The JavaScript get() proxy handler
JavaScript 中的 get() 代理处理程序允许您更改对象的属性访问行为。
按照以下语法使用代理对象上的 get() 代理处理程序。
get(target, property, receiver)
-
target − 这是目标对象。
-
property − 这是需要访问其值的对象。
-
receiver − 这是代理对象本身。
在下面的代码中,watch 对象包含品牌、颜色和价格属性。我们已经为 watch 对象创建了代理。
处理程序对象包含 get() 处理程序,并且在没有该处理程序的情况下返回属性值。否则,它将返回一条可读消息。
<html>
<body>
<div id = "output1">Brand: </div>
<div id = "output2">Price: </div>
<script>
const watch = {
brand: "Casio",
color: "Blue",
price: null,
}
const handler = {
get(object, property) {
return object[property] != null ? object[property] : "Property is null.";
}
}
const wathcProxy = new Proxy(watch, handler);
document.getElementById("output1").innerHTML += wathcProxy.brand;
document.getElementById("output2").innerHTML += wathcProxy.price;
</script>
</body>
</html>
Brand: Casio
Price: Property is null.
The JavaScript set() proxy handler
JavaScript 中的 set() 代理处理程序用于更改更新对象属性的默认行为。
按照以下语法使用 set() 代理处理程序。
set(target, property, value, receiver)
-
target − 这是目标对象。
-
property − 这是用于改变其值的属性。
-
value - 这是一个更新后的值。
-
receiver − 这是代理对象本身。
在下边的代码中,处理程序对象包含 set() 代理处理程序。set() 处理程序检查属性是否等于“price”。如果为真,它将用新值更新属性值。否则,它将“不可用”设置为对象属性。
<html>
<body>
<p id = "demo"> </p>
<script>
const output = document.getElementById("demo");
const watch = {
brand: "Casio",
color: "Blue",
price: null,
}
const handler = {
set(object, property, value) {
if (property === "price") {
object[property] = value;
}
else {
object[property] = "Not Available";
}
}
}
const wathcProxy = new Proxy(watch, handler);
wathcProxy.price = 2000;
wathcProxy.dial = "Round";
output.innerHTML += "Price: " + wathcProxy.price + "<br>";
output.innerHTML += "Dial: " + wathcProxy.dial + "<br>";
</script>
</body>
</html>
Price: 2000
Dial: Not Available
The JavaScript apply() proxy handler
apply() 代理处理程序用于更改函数调用的默认行为。
按照下边的语法使用 apply() 代理处理程序。
apply(target, thisArg, arguments)
-
target - 这是需要执行的目标函数。
-
thisArg - 它指的是在函数主体中应使用 this 关键字访问其元素的上下文。
-
arguments - 这是要传递给函数的参数数组。
在下边的代码中,getDetails 是为 getWatchDetails() 函数创建的代理对象。处理程序对象包含 apply() 方法并调用目标函数。
我们通过将 watch 对象作为参数传递来调用 getDetails() 代理。
<html>
<body>
<p id = "output"> </p>
<script>
const watch = {
brand: "Casio",
color: "Blue",
price: 2000,
}
const getWatchDetails = function (watch) {
return `Brand: ${watch.brand},
Color: ${watch.color},
price: ${watch.price}`;
}
const getDetails = new Proxy(getWatchDetails, {
apply(target, thisArg, args) {
return target(...args).toUpperCase();
}
});
document.getElementById("output").innerHTML += getDetails(watch);
</script>
</body>
</html>
BRAND: CASIO, COLOR: BLUE, PRICE: 2000
Uses of the Proxy Object in JavaScript
在这里,我们用示例说明了使用代理对象的好处。
For Validation
您可以在 JavaScript 中使用代理对象在更新属性值或向对象添加新属性时验证属性值。
在下边的代码中,numbers 对象包含 num1、num2 和 num3 属性。set() 代理处理程序检查新值是否大于当前值。如果为真,它将更新该值。否则,它将保留旧值。
<html>
<body>
<p id = "demo"> </p>
<script>
const output = document.getElementById("demo");
const numbers = {
num1: 10,
num2: 20,
num3: 30,
}
const handler = {
set(object, property, value) {
if (value > object[property]) {
// Validing the new value using the previous value
object[property] = value;
}
}
}
const numberProxy = new Proxy(numbers, handler);
numberProxy.num1 = 20;
numberProxy.num2 = 10;
output.innerHTML += "num1: " + numbers.num1 + ", num2: " + numbers.num2;
</script>
</body>
</html>
num1: 20, num2: 20
For Access Control
您还可以使用代理处理程序控制 JavaScript 中对象的访问权限。例如,您可以限制用户更新对象属性并使其变为只读。
在下边的代码中,无论何时尝试更新对象属性值时,它都将打印对象为只读的消息。
<html>
<body>
<p id = "demo"> </p>
<script>
const output = document.getElementById("demo");
const numbers = {
num1: 10,
num2: 20,
num3: 30,
}
const handler = {
set(object, property, value) {
output.innerHTML += "Object is read-only.<br>"
}
}
const numberProxy = new Proxy(numbers, handler);
numberProxy.num1 = 20;
output.innerHTML += "num1: " + numberProxy.num1;
</script>
</body>
</html>
Object is read-only.
num1: 10
Side Effects
当有人尝试访问或更新对象属性时,您可以调用函数或类方法。
在下面的示例中,emailValidator() 函数检查电子邮件中是否包含 '@'。如果为真,它将返回 true。否则,它将返回 false。
在 set() 代理处理程序中,我们根据 emailValidator() 函数的返回值更新属性值。
<html>
<body>
<p id = "output"> </p>
<script>
const emails = {
email1: "abcd@gmail.com",
}
// Function to validate the email
function emailValidator(email) {
if (email.includes("@")) {
return true;
} else {
return false;
}
}
const handler = {
set(object, property, value) {
if (emailValidator(value)) {
object[property] = value;
}
}
}
const emailProxy = new Proxy(emails, handler);
emailProxy.email1 = "nmc@gmail.com";
document.getElementById("output").innerHTML =
"email1: " + emailProxy.email1;
</script>
</body>
</html>
email1: nmc@gmail.com
但是,代理处理程序的使用并不受限制,我们无法在本教程中涵盖每种用例。因此,您可以探索更多代理处理程序的用例。
JavaScript Proxy Handlers List
在这里,我们列出了 JavaScript 中的所有代理处理程序。
Proxy Handler Methods
Sr.No. |
Proxy Handler |
Description |
1 |
apply() |
它改变了函数调用的默认行为。 |
2 |
construct() |
捕获新对象的构造。 |
3 |
defineProperty() |
改变定义新属性的行为。 |
4 |
deleteProperty() |
改变删除新属性的行为。 |
5 |
get() |
改变访问对象属性的行为。 |
6 |
getOwnPropertyDescriptor() |
捕获对象中 getOwnPropertyDescriptor() 方法。 |
7 |
getPrototypeOf() |
Trapping the internal methods. |
8 |
has() |
操纵检查对象是否包含 property。 |
9 |
isExtensible() |
捕获 Object 的 isExtensible() 方法。 |
10 |
ownKeys() |
改变 ownKeys() 方法的行为。 |
11 |
preventExtension() |
捕获阻止对象扩展。 |
12 |
set() |
改变添加新 property 或更新对象中 property 值的默认行为。 |
13 |
setPrototypeOf() |
定制 Object.setPrototypeOf() 方法。 |