1.代理的原理
var p=new Proxy(target,handler);
target 目标对象
handler 一个对象,其属性是执行操作的行为函数
const a = { name: "liu" }; ⇽--- emperor是目标对象
const b = new Proxy(a, { ⇽--- 通过Proxy构造器创建代理,传入对象emperor,以及包含get与set方的对象,用于处理对象属性的读写操作
get: (target, key) => {
report("Reading " + key + " through a proxy");
return key in target ? target[key]
: "Don't bother the a!"
},
set: (target, key, value) => {
report("Writing " + key + " through a proxy");
target[key] = value;
}
});
assert(a.name === "Komei", "The a's name is Komei");
assert(b.name === "Komei","We can get the name property through a proxy"); ⇽--- 分别通过目标对象和代理对象访问name属性
assert(a.nickname === undefined,"The a doesn’t have a nickname "); ⇽--- 直接访问目标对象上不存在的nickname属性将返回undefined
assert(b.nickname === "Don't bother the a!", "The proxy jumps in when we make inproper requests");⇽---通过代理对象访问时,将会检测到nickname属性不存在,并因此返回警告
b.nickname = "Tenno";
assert(a.nickname === "Tenno","The a now has a nickname");
assert(b.nickname === "Tenno","The nickname is also accessible through the proxy"); ⇽--- 通过代理对象添加nickname属性后,分别通过目标对象和代理对象均可访问nickname属性
2.使用代理检测性能
function isPrime(number){
if(number < 2) { return false; }
for(let i = 2; i < number; i++) {
if(number % i === 0) { return false; }
} ⇽--- 定义isPrime函数的简单实现
return true;
}
isPrime = new Proxy(isPrime, { ⇽--- 使用代理包装isPrime方法
apply: (target, thisArg, args) => { ⇽--- 定义apply方法,当代理对象作为函数被调用时将会触发该apply方法的执行
console.time("isPrime"); ⇽--- 启动一个计时器,记录isPrime函数执行的起
始时间
const result = target.apply(thisArg, args); ⇽--- 调用目标函数
console.timeEnd("isPrime"); ⇽--- 停止计时器的执行并输出结果
return result;
}
});
isPrime(1299827); ⇽--- 同调用原始方法一样,调用isPrime方法
使用isPrime函数作为代理的目标对象。同时,添加apply方法,当调用isPrime函数时就会调用apply方法。与之前的示例类似,我们将新创建的代理对象赋值给isPrime标识符。这样,我们无需修改isPrime函数内部代码,就可以调用apply方法实现isPrime函数的性能评估,程序代码的其余部分可以完全无视些变化。
3.使用代理实现负数组索引
通常直接访问数组最后几位元素没有那么优雅,相比于Python的负数组索引,JavaScript并没有这么方便,现在我们可以通过代理实现负数组索引,优雅的访问数组
const ninjas = ['a', 'b', 'c'];
console.log(ninjas[-2]);//js不支持数组负索引
console.log(ninjas.slice(-1));
function createArray(array) {
if (!Array.isArray(array)) {
throw new TypeError('不是数组,报错')
}
return new Proxy(array,{
get(target,key){
key=+key;
return target[key < 0 ? target.length + key : key];
},
set(target, key, value) {
key=+key;
return target[key<0?target.length+key:key]=value
}
})
}
const arr = ['a', 'b', 'c', 'd'];
const proxyArr = createArray(arr);
console.log(proxyArr[-2]);
4.代理的性能消耗
事实上,我们所有的操作都通过代理添加了一个间接层,使我们能够实现所有这些很酷的特性,但与此同时它引入了大量的额外的处理,会影响性能。
所以代理效率不高,所以在需要执行多次的代码中需要谨慎使用。建议进行性能测试。