JavaScript - 代理
JavaScript 中的代理
JavaScript 代理 是一种对象,它允许您包装特定对象并自定义该对象的基本操作,例如获取和设置对象属性。简而言之,使用代理对象,您可以为对象添加自定义行为。代理用于实现日志记录、缓存和安全等功能。
我们可以使用 JavaScript 中的 Proxy() 构造函数创建代理对象。该构造函数接受两个参数:目标对象和处理程序对象。它返回目标对象的新代理对象。
语法
以下是在 JavaScript 中创建代理对象的语法 -
const obj = new Proxy(targetObj, Handler);
在上述语法中,我们使用了带有 new 关键字的 Proxy() 构造函数。
参数
Proxy 构造函数接受两个参数。
targetObj − 它是一个目标对象,您需要为其创建代理对象并自定义其默认行为。
Handler − 它是一个包含自定义目标对象行为功能的对象。
示例
在下面的示例中,person 对象包含 name 和 age 属性。
我们为名为 proxyObj 的 person 对象定义了代理对象。此外,我们将 handler 对象作为 Proxy() 构造函数的参数传递。
在 handler 对象中,我们定义了用于访问对象属性的 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 = {
// 定义 getter
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 代理处理程序
JavaScript 中有多种可用的代理处理程序,我们在下面介绍了其中的一些。代理处理程序用于覆盖对象的默认行为。
JavaScript get() 代理处理程序
JavaScript 中的 get() 代理处理程序允许您更改对象的属性访问行为。
语法
按照以下语法将 get() 代理处理程序与代理对象一起使用。
get(target, property, receiver)
参数
target − 它是一个目标对象。
property − 它是一个需要访问其值的属性。
receiver − 它是一个代理对象本身。
示例
在下面的代码中,手表对象包含品牌、颜色和价格属性。我们为手表对象创建了代理。
处理程序对象包含 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.
JavaScript set() 代理处理程序
JavaScript 中的 set() 代理处理程序用于更改更新对象属性的默认行为。
语法
请按照以下语法使用 set() 代理处理程序。
set(target, property, value, receiver)
参数
target − 目标对象。
property − 属性值可更改。
value − 更新后的值。
receiver − 代理对象本身。
示例
在下面的代码中,处理程序对象包含 set() 代理处理程序。set() 处理程序检查属性是否等于"price"。如果是,则使用新值更新属性值。否则,将"Not Availability"设置为对象属性。
<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
JavaScript apply() 代理处理程序
apply() 代理处理程序用于更改函数调用的默认行为。
语法
请按照以下语法使用 apply() 代理处理程序。
apply(target, thisArg, argument)
参数
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
JavaScript 中代理对象的用法
这里,我们通过示例解释了使用代理对象的好处。
用于验证
您可以在 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]) {
// 使用先前的值验证新值
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
用于访问控制
您还可以使用代理处理程序在 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
副作用
当有人尝试访问或更新对象属性时,您可以调用这些函数或类方法。
示例
在下面的示例中,emailValidator() 函数检查电子邮件是否包含"@"。如果是,则返回 true。否则,返回 false。
在 set() 代理处理程序中,我们根据 emailValidator() 函数的返回值更新属性值。
<html>
<body>
<p id = "output"> </p>
<script>
const emails = {
email1: "abcd@gmail.com",
}
// 验证电子邮件的函数
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 代理处理程序列表
这里,我们列出了 JavaScript 中的所有代理处理程序。
代理处理程序方法
| 序号 | 代理处理程序 | 描述 |
|---|---|---|
| 1 | apply() | 它会更改函数调用的默认行为。 |
| 2 | construct() | 捕获 new 的构造对象。 |
| 3 | defineProperty() | 更改定义新属性的行为。 |
| 4 | deleteProperty() | 更改删除新属性的行为。 |
| 5 | get() | 更改访问对象属性的行为。 |
| 6 | getOwnPropertyDescriptor() | 捕获对象。 |
| 7 | getPrototypeOf() | 捕获内部方法。 |
| 8 | has() | 操作检查对象是否包含属性。 |
| 9 | isExtensible() | 捕获对象的 isExtensible() 方法。 |
| 10 | ownKeys() | 更改 ownKeys() 的行为方法。 |
| 11 | preventExtension() | 捕获对象的阻止扩展。 |
| 12 | set() | 更改对象添加新属性或更新属性值的默认行为。 |
| 13 | setPrototypeOf() | 自定义 Object.setPrototypeOf() 方法。 |
构造函数
| 序号 | 构造函数 | 描述 |
|---|---|---|
| 1 | Proxy() | 用于创建代理对象。 |
静态方法
| 序号 | 方法 | 描述 |
|---|---|---|
| 1 | revocable() | 它也用于创建一个新的代理对象,类似于 Proxy() 构造函数。 |

