在ES6中提供了Proxy构造函数,用来生成Proxy实例。关于Proxy,简单的理解就是,在对目标对象的访问之前加了一层拦截,所有对目标对象的访问操作,都会经过这层拦截。
基本的使用:
const proxy = new Proxy(target, handler);
target是目标对象,handler是一系列拦截行为。下面将介绍Proxy常用的几种拦截行为:
1、get()
get方法用于拦截对象中某个属性的读取操作。接受三个参数,依次目标对象、属性名和proxy实例本身。
const target = {
a: 1,
};
const handler = {
get: function (target, propKey) {
console.log('get');
return target[propKey];
},
};
const proxy = new Proxy(target, handler);
console.log(proxy.a);// get 1
2、set()
set方法用于拦截对象中某个属性的赋值操作。接受四个参数,依次为目标对象、属性名、属性值和proxy 实例本身。set方法需要返回一个布尔值,当返回为true时,表示赋值成功;返回为false时,在严格模式代码中,则会引发TypeError错误。
const target = {
a: 1,
};
const handler = {
set: function (target, propKey, propValue) {
console.log("set", propValue);
return true;
},
};
const proxy = new Proxy(target, handler);
proxy.a = 4;// set 4
3、apply()
apply方法用于拦截函数的调用、call和apply操作。接受三个参数,依次为目标函数对象、目标函数对象的执行上下文、目标函数对象的参数数组。
const target = () => {
console.log("target");
return "1";
};
const handler = {
apply: function (target, ctx, args) {
console.log("proxy");
return "2";
},
};
const proxy = new Proxy(target, handler);
console.log(proxy()); // proxy 2
4、has()
has()方法用来拦截in操作,即判断对象是否具有某个属性时,这个方法会生效。但对于for...in循环是不生效的。
const target = {
a: 1,
};
const obj = Object.create(target);
const handler = {
has: function (target, key) {
console.log('has');
return key in target;
},
};
const proxy = new Proxy(obj, handler);
console.log('a' in proxy); // has true
5、construct()
construct()方法用于拦截new命令。接受三个参数,目标对象,构造函数的参数数组,以及new命令的构造函数也就是代理构造函数。construct()拦截的是构造函数,所以它的目标对象必须是函数,否则就会报错。返回的必须是个对象,否则也会报错。
const target = function () {};
const handler = {
construct: function (target, args) {
console.log("construct");
return { key: args[0] };
},
};
const proxy = new Proxy(target, handler);
console.log(new proxy(2).key); //construct 2
6、deleteProperty()
deleteProperty方法用于拦截delete操作。接受两个参数,目标对象,目标对象属性值。如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。
const target = {
key: "1",
};
const handler = {
deleteProperty: function (target, key) {
console.log("deleteProperty");
delete target[key];
return true;
},
};
const proxy = new Proxy(target, handler);
delete proxy.key; // deleteProperty
console.log(target.key); // undefined
7、ownKeys()
ownKeys()方法用来拦截对象自身属性的读取操作。当使用Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()、Object.keys()、for...in循环,都会被拦截。
const target = {
key: "1",
a: "2",
b: "3",
};
const handler = {
ownKeys: function (target) {
console.log('ownKeys');
return ['key'];
},
};
const proxy = new Proxy(target, handler);
console.log(Object.keys(proxy)); // ownKeys ['key']
其他方法简介
getOwnPropertyDescriptor()方法拦截Object.getOwnPropertyDescriptor()。
getPrototypeOf()方法主要用来拦截获取对象原型。
isExtensible()方法拦截Object.isExtensible()操作。
preventExtensions()方法拦截Object.preventExtensions()。
setPrototypeOf()方法主要用来拦截Object.setPrototypeOf()方法。