ES6 Proxy
Proxy (代理器)作用: 运行我们在访问目标对象之前做一层拦截(拦截的过程允许自定义“代理”某些操作)。
1. ES6原生提供Proxy构造函数,用来生成Proxy实例。
var proxy = new Proxy(target, handler)
Proxy 对象的所有用法,都是上面这种形式。不同的是handler参数写法。
其中: target 参数表示要拦截的目标对象, handler参数也是一个对象,用于定制拦截行为
下面是一个简例:
var proxy = new Proxy({}, {
get: function(target, property) {
return "default value";
}
});
proxy.age // "default value"
proxy.name // "default value"
proxy.title // "default value"
上面实例代码:
第一个参数目标对象,是一个空对象;
第二个参数是一个配置对象,每一个被代理的目标对象,需要提供一个对应的处理函数,用于目标对象操作的拦截(拦截行为后提前做一些定制操作);
输出结果: 因为拦截操作总是返回“default value”, 所以访问任何属性都是返回“default value";
如果目标对象没有设置任何拦截就等同于直接操作原对象,如下例:
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.name = 'haha';
target.name // "haha"
Proxy 实例也可以作为其它对象的原型对象。
var proxy = new Proxy({}, {
get: function(target, property) {
return "default value";
}
});
let obj = Object.create(proxy);
obj.time // "default value"
同一个拦截器函数,允许设置拦截多个操作:
var handler = {
get: function(target, name) {
if (name === 'prototype') {
return Object.prototype;
}
return 'Hello, ' + name;
},
apply: function(target, thisBinding, args) {
return args[0];
},
construct: function(target, args) {
return {value: args[1]};
}
};
var fproxy = new Proxy(function(x, y) {
return x + y;
}, handler);
fproxy(1, 2) // 1
new fproxy(1, 2) // {value: 2}
fproxy.prototype === Object.prototype // true
fproxy.foo === "Hello, foo" // true
2. 代理器内置api:
(1) get (): get 方法用于拦截某个属性的读取操作。
(2) set(): set 方法用来拦截某个属性的赋值操作。
(3) apply(): apply 方法拦截函数的调用, call 和 apply操作。
(4) has(); has 方法用来拦截 HasProperty操作 (典型的操作就是in
运算符)
(5)construct(): construct 方法用于拦截new命令
(6)defineProperty(): defineProperty方法拦截了 Object.defineProperty操作(即:添加新属性时拦截)
(7)ownKeys(): ownKeys 方法用来拦截对象自身的读取操作
3. this 问题
虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this
关键字会指向 Proxy 代理