跳到主要内容

捕获器

2023年08月17日
柏拉文
越努力,越幸运

一、handler.apply()


**handler.apply()方法用于拦截函数的调用。target**必须是可被调用的。也就是说,它必须是一个函数对象。

1.1 语法

const proxy = new Proxy(target, {
apply(target, thisArg, argumentsList) {
}
});
  • target: 目标对象(函数)。target 必须是可被调用的。也就是说,它必须是一个函数对象。

  • thisArg: 被调用时的上下文对象

  • argumentsList: 被调用时的参数数组

1.2 返回值

apply方法可以返回任何值。

1.3 拦截场景

拦截proxy(...args)

const proxy = new Proxy(function(){},{
apply:function(target,thisArg,argumentsList){
console.log(argumentsList.join(','));
}
});

proxy('a','b','c');

拦截Reflect.apply()

拦截Function.prototype.apply()或者Function.prototype.call()

应用场景

  • 通过 handler 捕获函数的调用

二、handler.construct()


handler.construct() 方法用于拦截new操作符. 为了使new操作符在生成的Proxy对象上生效,用于初始化代理的目标对象自身必须具有[[Construct]]内部方法(即 new target 必须是有效的)。handler.construct() 必须返回一个对象,否则会报错。

2.1 语法

const proxy = new Proxy(target, {
construct(target, argumentsList, newTarget) {
}
});
  • target: 目标对象

  • argumentsList: constructor的参数列表

  • newTarget: 最初被调用的构造函数,就上面的例子而言是p

2.2 返回值

**construct**方法必须返回一个对象

2.3 拦截场景

拦截new proxy(...args)

const proxy = new Proxy(function() {},{
construct:function(target,argumentsList,newTarget){
console.log(argumentsList.join(','));
return {}
}
});

const p = new proxy('a','b','c');
console.log(p);

三、handler.defineProperty()


**handler.defineProperty()用于拦截对对象的Object.defineProperty()**操作。

3.1 语法

const proxy = new Proxy(target, {
defineProperty(target, property, descriptor) {
}
});
  • target: 目标对象

  • property: 待检索其描述的属性名

  • descriptor: 待定义或修改的属性的描述符

3.2 返回值

**defineProperty方法必须以一个Boolean**返回,表示定义该属性的操作成功与否。

3.3 拦截场景

拦截 Object.defineProperty()

const proxy = new Proxy({},{
defineProperty:function(target,prop,descriptor){
console.log(prop);
return true;
}
});

Object.defineProperty(proxy,'name',{
value:'柏拉图',
writable:true,
enumerable:true,
configurable:true
});

console.log(proxy);
const proxy = new Proxy({},{
defineProperty:function(target,prop,descriptor){
console.log(prop);
return Reflect.defineProperty(target,prop,descriptor);
}
});

Object.defineProperty(proxy,'name',{
value:'柏拉图',
writable:true,
enumerable:true,
configurable:true
});

四、handler.deleteProperty()


**handler.deleteProperty()方法用于拦截对对象属性的delete**操作。

4.1 语法

const proxy = new Proxy(target, {
deleteProperty: function(target, property) {

}
});
  • target: 目标对象

  • property: 待删除的属性名

4.2 返回值

**deleteProperty**必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除。

4.3 拦截场景

拦截Reflect.deleteProperty()

拦截delete proxy[foo]delete proxy.foo

const proxy = new Proxy({},{
deleteProperty:function(target,prop){
console.log(prop);
return true;
}
});

delete proxy.a;

五、handler.get()


**handler.get()**方法用于拦截对象的读取属性操作。

5.1 语法

const proxy = new Proxy(target, {
get: function(target, property, receiver) {
}
});
  • target: 目标对象

  • property: 被获取的属性名

  • receiver: Proxy或者继承Proxy的对象(表示代理对象本身或者继承与代理对象的对象)。为了确保拦截器函数中正确的传递上下文访问

5.2 返回值

get方法可以返回任何值。

5.3 拦截场景

拦截Reflect.get()

拦截 proxy[foo]和 proxy.bar

const proxy = new Proxy({},{
get:function(target,prop,receiver){
console.log(prop);
return 10
}
});

console.log(proxy.a);

拦截访问原型链上的属性: Object.create(proxy)[foo]

六、handler.getOwnPropertyDescriptor()


**handler.getOwnPropertyDescriptor()方法是Object.getOwnPropertyDescriptor()**的钩子

6.1 语法

const proxy = new Proxy(target, {
getOwnPropertyDescriptor: function(target, prop) {
}
});
  • target: 目标对象

  • prop: 返回属性名称的描述

6.2 返回值

**getOwnPropertyDescriptor**方法必须返回一个 objectundefined

6.3 拦截场景

拦截Object.getOwnPropertyDescriptor()

const proxy = new Proxy({},{
getOwnPropertyDescriptor:function(target,prop){
console.log(prop);
return {value:'测试',writable:true,enumerable:true,configurable:true}
}
});

const result = Object.getOwnPropertyDescriptor(proxy,'a');
console.log(result)

七、handler.getPrototypeOf()


**handler.getPrototypeOf()**是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用。

7.1 语法

const proxy = new Proxy(obj, {
getPrototypeOf(target) {
...
}
});
  • target: 被代理的目标对象

7.2 返回值

getPrototypeOf 方法的返回值必须是一个对象或者 null

7.3 拦截场景

拦截__proto__

const proxy = new Proxy({},{
getPrototypeOf:function(target){
console.log(target);
return target;
}
});

console.log(proxy.__proto__);

拦截instanceof

拦截Object.getPrototypeOf()

拦截Reflect.getPrototypeOf()

拦截Object.prototype.isPrototypeOf()

八、handler.has()


**handler.has()方法是针对in**操作符的代理方法。

8.1 语法

const = new Proxy(target, {
has: function(target, prop) {
}
});
  • target: 目标对象

  • prop: 需要检查是否存在的属性

8.2 返回值

has 方法返回一个 boolean 属性的值.

8.3 拦截场景

拦截 foo in proxy

const proxy = new Proxy({},{
has(target,key){
return Reflect.has(target,key);
}
});

console.log('a' in proxy);

拦截 Reflect.has()

拦截 with(proxy) { (foo); }

拦截 foo in Object.create(proxy)

九、handler.isExtensible()


handler.isExtensible()方法用于拦截对对象的Object.isExtensible()

9.1 语法

const proxy = new Proxy(target, {
isExtensible: function(target) {
}
});
  • target: 目标对象

9.2 返回值

isExtensible方法必须返回一个 Boolean 值或可转换成Boolean的值。

9.3 拦截场景

拦截Object.isExtensible()

const proxy = new Proxy({},{
isExtensible:function(target){
console.log(target);
return true
}
});

Object.isExtensible(proxy);

拦截Reflect.isExtensible()

十、handler.ownKeys()


handler.ownKeys()方法用于拦截Reflect.ownKeys()

10.1 语法

const proxy = new Proxy(target, {
ownKeys: function(target) {
}
});
  • target: 目标对象.

10.2 返回值

ownKeys 方法必须返回一个可枚举对象.

10.3 拦截场景

拦截for……in

const proxy = new Proxy({},{
ownKeys(target){
return Reflect.ownKeys(target);
}
})

for(const key in proxy){

}

拦截Object.keys()

const proxy = new Proxy({},{
ownKeys:function(target){
console.log(target);
return ['a','b','c']
}
});

console.log(Object.getOwnPropertyNames(proxy));

拦截Reflect.ownKeys()

拦截Object.getOwnPropertyNames()

拦截Object.getOwnPropertySymbols()

十一、handler.preventExtensions()


handler.preventExtensions() 方法用于设置对**Object.preventExtensions()**的拦截

11.1 语法

const proxy = new Proxy(target, {
preventExtensions: function(target) {
}
});
  • target: 所要拦截的目标对象.

11.2 返回值

preventExtensions 方法返回一个布尔值.

11.3 拦截场景

拦截Object.preventExtensions()

const proxy = new Proxy({},{
preventExtensions:function(target){
console.log(target);
Reflect.preventExtensions(target);
return true;
}
});

console.log(Object.preventExtensions(proxy));

拦截Reflect.preventExtensions()

十二、handler.set()


**handler.set()**方法是设置属性值操作的捕获器。

12.1 语法

const p = new Proxy(target, {
set: function(target, property, value, receiver) {
}
});
  • target: 目标对象

  • property: 将被设置的属性名或 Symbol

  • value: 新属性值

  • receiver: 最初被调用的对象。通常是 proxy 本身,但 handlerset 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。

12.2 返回值

set() 方法应当返回一个布尔值。

  • 返回 true 代表属性设置成功。

  • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常。

12.3 拦截场景

拦截Reflect.set()

拦截 Object.create(proxy)[foo] = bar

拦截proxy[foo] = barproxy.foo = bar

十三、handler.setPrototypeOf()


handler.setPrototypeOf() 方法主要用来拦截 Object.setPrototypeOf().

13.1 语法

const proxy =  new Proxy(target, {
setPrototypeOf: function(target, prototype) {
}
});
  • target: 被拦截目标对象.

  • prototype: 对象新原型或为null.

13.2 返回值

如果成功修改了[[Prototype]], setPrototypeOf 方法返回 true,否则返回 false

13.3 拦截场景

拦截Object.setPrototypeOf()

拦截Reflect.setPrototypeOf()