什么是代理?
原理:
代理(proxy)是es6新增的功能,可以用来自定义对对象操作的结果。在官方文档中对Proxy
的解释是:
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。
也就是说:Proxy
对象就是可以让你去对JavaScript中的一切合法对象的基本操作进行自定义.然后用你自定义的操作去覆盖其对象的基本操作.也就是当一个对象去执行一个基本操作时,其执行的过程和结果是你自定义的,而不是对象的。
其实也可以理解为拦截操作,当你对对象作出某些行为,代理会先拦截下来,然后执行代理里自定义的方法。通俗点就是不管你做啥操作,只要被我拦截了,你就得听我的话,执行我的操作,哪怕是拦截下来啥也不做。
语法:
首先Proxy的语法是:
let pox = new Proxy(target, handler);
其中有
-
target
是你要代理的对象.它可以是JavaScript中的任何合法对象.如: (数组, 对象, 函数等等) -
handler
是你要自定义操作方法的一个集合. -
pox
是一个被代理后的新对象,它拥有target
的一切属性和方法.只不过其行为和结果是在handler
中自定义的
让我们看看例子解析
let obj = {
name: "tom"
};
console.log(obj.name);
let pox = new Proxy(obj, {
set(target, key, val) {
console.log('我被执行了');
target[key] = val;
},
get(target, key) {
console.log('你的get被我代理了,你得听我的');
return target[key]
}
})
pox.name = "terry" //设置了属性执行console.log('我被执行了') 输出我被执行了
console.log(pox.name);//你的get被我代理了,你得听我的 terry
console.log(obj.name);//terry
从上面这段代码中,我可以很清楚的看到Proxy
对象的作用.即是之前所受的用于定义基本操作的自定义行为.同样的get
和set
操作.没有没代理的对象所得的结果是其JavaScript本身的执行机制运行后所得到的.而被代理了的对象的结果则是我们自定义的,如果把代理的执行语句去掉一部分或者改变其中的代码使其不对被代理对象造成影响会出现什么结果。
let obj = {
name: "tom"
};
console.log(obj.name);
let pox = new Proxy(obj, {
set(target, key, val) {
console.log('我被执行了');
// target[key] = val;
},
get(target, key) {
console.log('你的get被我代理了,你得听我的');
return '哈哈哈'
// return target[key]
}
})
pox.name = "terry" //设置了属性执行console.log('我被执行了') 输出 我被执行了
console.log(pox.name);//你的get被我代理了,你得听我的 哈哈哈
console.log(obj.name);//tom
经过第一段代码的分析后,很清楚的看出第二段代码的操作里并没有对被代理对象作出影响,由此可见只要被代理拦截了,里面的代码如何执行都有我们自己自定义。这就是代理。
代理的运用
从上面我们了解了代理是什么,执行了什么。那么代理如何去运用呢?其实不难看出,上面我们对 对象的属性的设置和读取进行了拦截。而这些代理的方法实际上是handler
上的去多方法,而handler本
身就是ES6所新设计的一个对象.它的作用就是用来自定义代理对象的各种可代理操作。它本身一共有13中方法,每种方法都可以代理一种操作.其13种方法如下
handler.getPrototypeOf()
// 在读取代理对象的原型时触发该操作,比如在执行 Object.getPrototypeOf(proxy) 时。
handler.setPrototypeOf()
// 在设置代理对象的原型时触发该操作,比如在执行 Object.setPrototypeOf(proxy, null) 时。
handler.isExtensible()
// 在判断一个代理对象是否是可扩展时触发该操作,比如在执行 Object.isExtensible(proxy) 时。
handler.preventExtensions()
// 在让一个代理对象不可扩展时触发该操作,比如在执行 Object.preventExtensions(proxy) 时。
handler.getOwnPropertyDescriptor()
// 在获取代理对象某个属性的属性描述时触发该操作,比如在执行Object.getOwnPropertyDescriptor(proxy, "foo") 时。
handler.defineProperty()
// 在定义代理对象某个属性时的属性描述时触发该操作,比如在执行 Object.defineProperty(proxy, "foo", {}) 时。
handler.has()
// 在判断代理对象是否拥有某个属性时触发该操作,比如在执行 "foo" in proxy 时。
handler.get()
// 在读取代理对象的某个属性时触发该操作,比如在执行 proxy.foo 时。
handler.set()
// 在给代理对象的某个属性赋值时触发该操作,比如在执行 proxy.foo = 1 时。
handler.deleteProperty()
// 在删除代理对象的某个属性时触发该操作,比如在执行 delete proxy.foo 时。
handler.ownKeys()
// 在获取代理对象的所有属性键时触发该操作,比如在执行 Object.getOwnPropertyNames(proxy) 时。
handler.apply()
// 在调用一个目标对象为函数的代理对象时触发该操作,比如在执行 proxy() 时。
handler.construct()
// 在给一个目标对象为构造函数的代理对象构造实例时触发该操作,比如在执行new proxy() 时。
代理的作用
对于代理模式
Proxy
的作用主要体现在三个方面:1、 拦截和监视外部对对象的访问
2、 降低函数或类的复杂度
2、 在复杂操作前对操作进行校验或对所需资源进行管理