在 JavaScript 中,Proxy 是一种能够拦截并包装底层对象的机制。使用 Proxy 可以拦截对象上的操作,例如读取属性、写入属性、函数调用等,从而允许我们修改对象的默认行为。
Proxy 可以用来实现很多功能,比如:数据绑定、类型检查、缓存等等。
下面是一个简单的示例,展示了如何使用Proxy来代理一个对象,并拦截对其属性的访问和赋值操作:
const targetObj= {
name: 'John',
age: 30
};
const proxyObj=newProxy(targetObj, {
get(target, property) {
console.log(`Getting ${property}...`);
returntarget[property];
},
set(target, property, value) {
console.log(`Setting ${property}to ${value}...`);
target[property] =value;
}
});
console.log(proxyObj.name); // Output: Getting name... John
proxyObj.age=31; // Output: Setting age to 31...
console.log(proxyObj.age); // Output: Getting age... 31
在上面的代码中,我们使用了new Proxy()构造函数来创建一个代理对象proxyObj,并将原始对象targetObj作为其第一个参数传递进去。第二个参数是一个拦截器对象,用于定义代理对象的行为。
在拦截器对象中,我们定义了get()和set()方法,用于拦截对代理对象属性的访问和赋值操作。在get()方法中,我们打印了一条日志,并返回原始对象的属性值。在set()方法中,我们同样打印了一条日志,并将属性的值赋值给原始对象。
下面是一个简单的示例,使用 Proxy 来实现一个简单的缓存功能。
let expensiveFunction=function() {
// 长时间运行的代码
};
let cache=newMap();
let proxy=newProxy(expensiveFunction, {
apply: function(target, thisArg, argumentsList) {
letcacheKey=JSON.stringify(argumentsList);
if (cache.has(cacheKey)) {
returncache.get(cacheKey);
}
letresult=target.apply(thisArg, argumentsList);
cache.set(cacheKey, result);
returnresult;
}
});
// 第一次调用 expensiveFunction
console.time('expensiveFunction');
proxy('foo', 'bar');
console.timeEnd('expensiveFunction');
// 第二次调用 expensiveFunction
console.time('expensiveFunction');
proxy('foo', 'bar');
console.timeEnd('expensiveFunction');
在这个示例中,我们定义了一个 expensiveFunction 函数,它是一个长时间运行的代码。我们希望将其缓存起来,以便后续调用时能够快速访问缓存结果。
为了实现这个功能,我们使用了一个 Map 对象来存储缓存结果。然后,我们使用 Proxy 对 expensiveFunction 进行了包装,并重写了它的 apply 方法。在 apply 方法中,我们首先使用参数列表生成一个缓存键,并检查是否存在缓存结果。如果存在缓存结果,我们直接返回缓存结果;否则,我们执行 expensiveFunction 并将结果缓存起来。
这样,当我们第一次调用 expensiveFunction 时,它会执行长时间运行的代码并将结果缓存起来。当我们第二次调用 expensiveFunction 时,它会直接返回缓存结果,避免了重复执行长时间运行的代码。