跳到主要内容

ES6:Proxy代理

· 阅读需 4 分钟

proxy代理,就是在目标对象的前面设置一个拦截层,外界在访问这个对象的时候,必须经过拦截层。 我们可以在拦截层做一些过滤或者是改写的操作。

const proxy = new Proxy({}, {
get: () => {
console.log("get");
},
set: () => {
console.log("set")
}
})

proxy.count = 1; // set
++proxy.count; // get

Proxy接受两个参数,第一个参数是拦截目标对象;第二个参数是设置拦截的操作,所谓的拦截,一般都是有一些操作行为的,如果在拦截层没有设置任何操作的话,就会直接访问目标对象。

Proxy支持的拦截操作

get(target,Prophet,receiver)

拦截对象的读取属性操作。

const proxy = new Proxy({ name: "duXin", count: 90 }, {
get: () => {
console.log("get");
return 100
},
})

console.log(proxy.name)

在访问目标对象的时候,无论是name属性还是count属性,都会返回100,因为在拦截层设置读取属性时都返回100。

set()

方法是设置属性值操作的捕获器。

const proxy_set = new Proxy({}, {
set: function (target, prop, value, receiver) {
target[prop] = value;
console.log('property set: ' + prop + ' = ' + value);
return true;
}
})

console.log("======proxy_set=======")
console.log('name' in proxy_set); // false
proxy_set.name = 'duXin'; // property set: name = duXin

console.log('name' in proxy_set); // true

has()

对in操作符的代理方法。

const targetObj = {
_secret: 'easily scared',
eyeCount: 4
};
const proxy_has = new Proxy(targetObj, {
has: (target, key) => {
console.log("key==",key)
if (key.includes('_')) {
return false;
}
return key in target;
}
})

console.log('eyeCount' in targetObj); // true
console.log('_secret' in proxy_has); // false

construct()

拦截new操作符,返回的是一个对象。

function proxy_construct_obj(disposition){
this.disposition = disposition;
}
const proxyConstruct = new Proxy(proxy_construct_obj, {
construct: function (target, args) {
return new target(...args);
}
})

console.log(new proxyConstruct("duXinYue").disposition)

apply()

拦截函数的调用。 语法:

var p = new Proxy(target, {
apply: function(target, thisArg, argumentsList) {
}
});

target:目标对象,也就是函数 thisArg:被调用时的上下文对象 argumentsList:被调用时的参数,是一个类数组。

声明一个函数:

function sum(a, b) {
return a + b;
}

const proxy_apply = new Proxy(sum, {
apply: (target,thisArg, argumentsList) => {
console.log("target",target,thisArg, argumentsList)
return target(argumentsList[0], argumentsList[1]) * 10;
}
})

console.log(proxy_apply(1,2)); //30

defineProperty()

拦截对象的 Object.defineProperty() 操作符。 这是语法: defineProperty: function(target, property, descriptor) {} target:目标对象, property:被检索的属性名 descriptor:待定义或者修改的属性的描述符

defineProperty的返回值必须是Boolean值,表示对该属性操作是否成功。

var desc = { configurable: true, enumerable: true, value: 10 };
var defineProperty = new Proxy(desc, {
defineProperty: function (target, prop, descriptor) {
console.log('called: ' + prop);
Reflect.defineProperty(target, prop, descriptor);
}
});

defineProperty.name = "908"
console.log("obj", defineProperty); // { configurable: true, enumerable: true, value: 10, name: '908' }