代理——Proxy
在ES6中,新增了一个类Proxy,Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
- 如果希望监听一个对象的相关操作,那么可以先创建一个代理对象。
- 之后对该对象的所有操作,都通过代理对象来完成。
Proxy的基本使用
语法
const p = new Proxy(target, handler)
target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。 如果我们想要侦听某些具体的操作,那么就可以在handler中添加对应的捕捉器(Trap)
Proxy的get和set的捕获
set
的四个参数
target
:目标对象property
:将被设置的keyvalue
:新值receiver
: 调用的代理对象get
的三个参数
target
:目标对象property
:将被设置的keyreceiver
: 调用的代理对象
实例:
const obj = {
name: "abc",
age: 18,
};
const objProxy = new Proxy(obj, {
get(target, property, receiver) {
console.log("get捕获", property);
return target[property];
},
set(target, property, value, receiver) {
console.log("set捕获", property);
target[property] = value;
},
has(target, p) {
console.log("has捕获", p);
return p in target;
},
deleteProperty(target, p) {
console.log("deleteProperty捕获", p);
delete target[p];
},
});
console.log(objProxy.name);
objProxy.age = 38;
console.log(objProxy);
console.log("height" in objProxy);
delete objProxy["age"];
console.log(objProxy);
Proxy的所有捕获器
in 操作符的捕捉器。
属性读取操作的捕捉器。
属性设置操作的捕捉器。
delete 操作符的捕捉器。
Object.getPrototypeOf 方法的捕捉器。
Object.setPrototypeOf 方法的捕捉器。
Object.isExtensible 方法的捕捉器。
Object.preventExtensions 方法的捕捉器。
Object.getOwnPropertyDescriptor 方法的捕捉器。
Object.defineProperty 方法的捕捉器。
Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
函数调用操作的捕捉器。
new 操作符的捕捉器。
Receiver的作用
如果源对象(obj)有setter、getter的访问器属性,那么可以通过receiver来改变里面的this;
反射——Reflect
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与Proxy的方法相同。
Reflect不是一个函数对象,因此它是不可构造的。
Reflect的所有静态方法
所有静态方法与Proxy的所有捕获器相对应。
对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。
对构造函数进行 new操作,相当于执行 new target(…args)。
和 Object.defineProperty() 类似。如果设置成功就会返回 true
作为函数的delete操作符,相当于执行 delete target[name]。
获取对象身上某个属性的值,类似于 target[name]。
类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符, 否则返回 undefined.
判断一个对象是否存在某个属性,和 in运算符 的功能完全相同。
返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable影响).
类似于 Object.preventExtensions()。返回一个Boolean。
将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。
设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回true。
:::info
Reflect主要提供了很多操作JavaScript对象的方法,有点像Object中操作对象的方法;
比如Reflect.getPrototypeOf(target)类似于 Object.getPrototypeOf();
比如Reflect.defineProperty(target, propertyKey, attributes)类似于Object.defineProperty() ;
尽管二者之间存在 某些细微上的差别 .
:::
实例:
const obj = {
name: "abc",
age: 18,
};
const objProxy = new Proxy(obj, {
get(target, property, receiver) {
console.log("get捕获", property);
return Reflect.get(target, property, receiver);
},
set(target, property, value, receiver) {
console.log("set捕获", property);
Reflect.set(target, property, value, receiver)
},
has(target, p) {
console.log("has捕获", p);
return Reflect.has(target, p)
},
deleteProperty(target, p) {
console.log("deleteProperty捕获", p);
Reflect.deleteProperty(target, p)
},
});
console.log(objProxy.name);
objProxy.age = 38;
console.log(objProxy);
console.log("height" in objProxy);
delete objProxy["age"];
console.log(objProxy);