内容简介
代理可以捕获13种不同的基本操作。这些操作有各自不同的反射API方法、参数、关联ECMAScript操作和不变式。 有几种不同的JavaScript操作会调用同一个捕获器处理程序。对于在代理对象上执行的任何一种操作,只会有一个捕获处理程序被调用,不会存在重复捕获的情况。 只要在代理上调用,所有的捕获器都会拦截它们对应的反射API操作。
1.get()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
get ( target, property, receiver) {
console. log ( 'get()' ) ;
return Reflect. get ( ... arguments)
}
} ) ;
proxy. foo;
get捕获器在获取属性值的操作中被调用,对应的反射API方法是Reflect.get()。 get捕获器的返回值无限制。 get捕获器能够拦截的操作: (1)proxy.property (2)proxy[property] (3)Object.create(proxy)[property] (4)Reflect.get(proxy,property,receiver) get捕获器处理程序参数 (1)target:目标对象。 (2)property:引用的目标对象上的字符串键属性。 (3)receiver:代理对象或继承代理对象的对象。 get捕获器IDE捕获不定式 (1)如果target.property不可写不可配置,则处理程序返回的值必须与target.property匹配。 (2)如果target.property不可配置且[[get]]特性为undefined,处理程序的返回值也必须是undefined。
2.set()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
set ( target, property, value, receiver) {
console. log ( 'set()' ) ;
return Reflect. set ( ... arguments) ;
}
} ) ;
proxy. foo = 'bar' ;
set捕获器在设置属性值的操作中被调用,对应的反射API为Reflect.set()。 set捕获器的返回值: (1)true:表示成功; (2)false:表示失败,严格模式下会抛出TypeError。 set捕获器可以拦截的操作: (1)proxy.property = value (2)proxy[property] = value (3)proxy.create(proxy)[property] = value (4)proxy.set(proxy,property,value,receiver) set捕获器处理程序参数 (1)target:目标对象。 (2)property:引用的目标对象上的字符串键属性。 (3)value:要赋给属性的值。 (4)receiver:接收最初赋值的对象。 set捕获器不变式 (1)如果target.property不可写不可配置,则不能修改目标属性的值。 (2)如果target.property不可配置且[[set]]特性为undefined,则不能修改目标属性的值。 (3)在严格模式下,处理程序中返回false会抛出TypeError。
3.has()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
has ( target, property ) {
console. log ( 'has()' ) ;
return Reflect. has ( ... arguments)
}
} ) ;
'foo' in proxy;
has捕获器会在in操作符中被调用,对应的反射API方法为Reflect.has()。 has捕获器必须返回布尔值,表示属性是否存在。返回非布尔值会被转型为布尔值 has捕获器拦截的操作: (1)property in proxy (2)property in Object.create(proxy) (3)with(proxy){(property);} (4)Reflect.has(proxy,property) 捕获器处理程序参数 (1)target:目标对象 (2)property:引用的目标对象上的字符串属性 捕获器不变式 (1)如果target.property存在且不可配置,则处理程序必须返回true。 (2)如果target.property存在且目标对象不可扩展,则处理程序必须返回true。
4.defineProperty()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
defineProperty ( target, property, descriptor ) {
console. log ( 'defineProperty()' ) ;
return Reflect. defineProperty ( ... arguments) ;
}
} )
Object. defineProperty ( proxy, 'foo' , { value: 'bar' } ) ;
defineProperty捕获器会在Object.defineProperty()中被调用,对应的反射API方法为Reflect.defineProperty()。 defineProperty捕获器必须先返回布尔值,表示属性是否成功定义。返回非布尔值会被转型为布尔值。 defineProperty捕获器拦截的操作: (1)Object.defineProperty(proxy,property,descriptor) (2)Reflect.defineProperty(proxy,property,descriptor) defineProperty捕获器处理程序参数: (1)target:目标对象 (2)property:引用的目标对象上的字符串键属性。 (3)descriptor:包含可选的enumberable、configurable、writable、value、get和set定义的对象。 defineProperty捕获器不变式: (1)如果目标对象不可扩展,则无法定义属性。 (2)如果目标对象有一个可配置的属性,则不能添加同名的不可配置属性。 (3)如果目标对象有一个不可配置的属性,则不能添加同名的可配置属性。
5.getOwnPropertyDescriptor()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
getOwnPropertyDescriptor ( target, property ) {
console. log ( 'getOwnPropertyDescriptor()' ) ;
return Reflect. getOwnPropertyDescriptor ( ... arguments) ;
}
} )
getOwnPropertyDescriptor捕获器会在Object.getOwnPropertyDescriptor()中被调用,对应的反射API方法为Reflect.getOwnPropertyDescriptor(). getOwnPropertyDescriptor捕获器必须返回对象,或者在属性不存在时返回undefined。 getOwnPropertyDescriptor捕获器拦截的操作: (1)Object.getOwnPropertyDescriptor(proxy,property) (2)Reflect.getOwnPropertyDescriptor(proxy,property) getOwnPropertyDescriptor捕获器处理程序参数: (1)target:目标对象。 (2)property:引用的目标对象上的字符串键属性。 getOwnPropertyDescriptor捕获器不变式 (1)如果自有的target.property存在且不可配置,则处理程序必须返回一个表示该属性存在的对象。 (2)如果自有的target.property存在且可配置,则处理程序必须返回表示该属性可配置的对象。 (3)如果自有的target.property存在且target不可扩展,则处理程序必须返回一个表示该属性存在的对象。 (4)如果target.property不存在且target不可扩展,则处理程序必须返回undefined表示该属性不存在。 (5)如果target.property不存在,则处理程序不能返回表示该属性可配置的对象。
6.deleteProperty()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
deleteProperty ( target, property ) {
console. log ( 'deleteProperty()' ) ;
return Reflect. deleteProperty ( ... arguments)
}
} ) ;
delete proxy. foo;
deleteProperty捕获器会在delete操作符中被调用,对应的反射API方法会Reflect.deleteProperty()。 deleteProperty捕获器必须返回布尔值,表示删除属性是否成功,返回非布尔值会被转型为布尔值。 deleteProperty捕获器拦截的操作: (1)delete proxy.property (2)delete proxy[property] (3)Reflect.deleteProperty(proxy,property) deleteProperty捕获器处理程序参数: (1)target:目标对象。 (2)property:引用的目标对象上的字符串键属性。 deleteProperty捕获器不变式:如果自有的target.property存在且不可配置,则处理程序不能删除这个属性。
7.ownKeys()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
ownKeys ( target ) {
cosnole. log ( 'ownKeys()' ) ;
return Reflect. ownKeys ( ... arguments)
}
} )
Object. keys ( proxy) ;
ownKeys捕获器会在Object.keys()及类似方法中被调用。对应的反射API方法为Reflect.ownKeys()。 ownKeys捕获器必须返回包含字符串或符号的可枚举对象。 ownKeys捕获器拦截的操作: (1)Object.getOwnPropertyNames(proxy) (2)Object.getOwnPeopertySymbols(proxy) (3)Object.keys(proxy) (4)Reflect.wonKeys(proxy) ownKeys捕获器处理程序参数: (1)target:目标对象。 ownKeys捕获器不变式: (1)返回的可枚举对象必须包含target的所有不可配置的自有属性。 (2)如果target不可扩展,则返回可枚举对象必须准确地包含自有属性键。
8.getPrototypeOf()
const mytarget = { } ;
const proxy = new Proxy ( myTarget, {
getPrototypeOf ( target ) {
console. log ( 'getProptyoeOf()' ) ;
return Reflect. getPrototypeOf ( ... arguments) ;
}
} ) ;
Object. getPrototypeOf ( proxy) ;
getPrototypeOf捕获器会在Object.getPrototypeOf()中被调用,对应的反射API方法为Reflect.getPrototypeOf()。 getPrototypeOf必须返回对象或null。 getPrototypeOf拦截的操作: (1)Object.getPrototypeOf(proxy) (2)Reflect.getPrototypeOf(proxy) (3)proxy.__proto__
(4)Object.prototype.isPrototypeOf(proxy) (5)proxy instanceof Object getPrototypeOf捕获器处理程序参数 (1)target:目标对象。 getPRototypeOf捕获器不变式:如果target不可扩展,则Object.getPrototypeOf(proxy)唯一有效的返回值就是Object.getPrototypeOf(target)的返回值
9.setPrototypeOf()
const myTarget = { }
const proxy = new Proxy ( myTarget, {
setPrototypeOf ( target, prototype ) {
console. log ( 'setPrototypeOf()' ) ;
return Reflect. setPrototypeOf ( ... arguments)
}
} ) ;
Object. setPrototypeOf ( proxy, Object) ;
setPrototypeOf捕获器会在Object.setPrototypeOf()中被调用。对应的反射API方法为Reflect.getPrototypeOf()。 setPrototypeOf捕获器必须返回布尔值,表示原型赋值是否成功。返回非布尔值会被转型为布尔值。 setPrototypeOf捕获器拦截的操作: (1)Object.setPrototypeOf(proxy) (2)Reflect.setPrototypeOf(proxy) setPrototypeOf捕获器处理程序参数 (1)target:目标对象。 (2)prototype:target的替代原型,如果是顶级原型则为null。 setPrototypeOf捕获器不变式:如果target不可扩展,则唯一有效的prototype参数就是Object.getPrototypeOf(target)的返回值。
10.isExtensible()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
isExtensible ( target ) {
console. log ( 'isExtensible()' ) ;
return Reflect. isExtensible ( ... arguments)
}
} ) ;
Object. isExtensible ( proxy) ;
isExtensible捕获器会在Object.isExtensible()中被调用,对应的反射API方法为Reflect.isExtenSible()。 isExtensible捕获器必须返回布尔值,表示target是否可扩展。返回非布尔值会被转型为布尔值。 isExtensible捕获器拦截的操作: (1)Object.isExtensible(proxy) (2)Reflect.isExtensible(proxy) isExtensible捕获器处理程序参数: (1)target:目标对象 isExtensible捕获不变式: (1)如果target可扩展,则处理程序必须返回true。 (2)如果target不可扩展,则处理程序必须返回false。
11.preventExtensions()
const myTarget = { } ;
const proxy = new Proxy ( myTarget, {
preventExtensions ( target ) {
console. log ( 'preventExtensions()' ) ;
return Reflect. preventExtensions ( ... arguments)
}
} ) ;
Object. preventExtensions ( proxy) ;
preventExtensions捕获器会在Object.preventExtensions()中被调用。对应的反射API方法为Reflect.preventExtensions()。 preventExtensions捕获器必须返回布尔值,表示target是否已经不可扩展。返回非布尔值会被转型为布尔值。 preventExtensions捕获器拦截的操作: (1)Object.preventExtensions(proxy) (2)Reflect.preventExtensions(proxy) preventExtensions捕获器处理程序参数: (1)target:目标对象 preventExtensions捕获器不变式:如果Object.isExtensible(proxy)是false,则处理程序必须返回true
12.apply()
const myTarget = ( ) => { } ;
const proxy = new Proxy ( myTarget, {
apply ( target, thisArg, ... argumentsList ) {
console. log ( 'apply()' ) ;
return Reflect . apply ( ... arguments)
}
} )
proxy ( ) ;
apply捕获器会在调用函数时中被调用。对应的反射API方法为Reflect.apply()。 apply捕获器返回值无限制。 apply捕获器拦截的操作: (1)proxy(…arguments) (2)Function.prototype.apply(thisArg,argumentsList) (3)Function/prototype.call(thisArg,…argumentsList) (4)Reflect.apply(target,thisArgument,argumentList) apply捕获器处理程序参数: (1)target:目标对象 (2)thisArg:调用函数时的this参数 (3)argumentsList:调用函数时的参数列表 apply捕获器不变式:target必须是一个函数对象
13.construct()
const myTarget = function ( ) { } ;
const proxy = new Proxy ( myTarget, {
construct ( target, argumentsList, newTarget ) {
console. log ( 'construct()' ) ;
return Reflect. construct ( ... arguments)
}
} ) ;
new proxy ;
construct捕获器会在new操作符中被调用。对应的反射API方法为Reflect.construct()。 construct捕获器必须返回一个对象。 construct捕获器拦截的操作: (1)new proxy(…argument) (2)Reflect.construct(target, argumentsList, newTarget) construct捕获器处理程序参数 (1)target:目标构造函数 (2)argumentsList:传给目标构造函数的参数列表 (3)newTarget:最初被调用的构造函数 construct捕获器不变式:target必须可以用作构造函数