Proxy catcher and reflection method
Source JavaScript advanced programming
The agent can capture 13 different basic operations. These basic operations have their own reflection API methods, parameters, associated ECMAScript operations, and invariants.
get()
The get () catcher will be called in the operation of getting the property value. The method of the corresponding reflection API is Reflect.get()
// get() const test1={ name:'yihen' } const proxy=new Proxy(test1,{ get(target,property,receiver){ console.log('Already called get()') return Reflect.get(...arguments); } }) //get() has already been called console.log(proxy.name);// yihen
- Return value
Unlimited return value
- Intercepted operation
- proxy.property
- proxy[property]
- Object.create(proxy)[property]
- Reflect.get(proxy,property,receiver)
- Catcher handler parameters
- Target: target object
- Property: the string key property on the referenced target object
- receiver: a proxy object or an object that inherits a proxy object
- Catcher invariant
-
If target.property is not writable and configurable, the value returned by the handler must match target.property
-
If target.property is not configurable and the [[Get]] attribute is undefined, the return value of the handler must also be undefined
set()
The set () catcher is called in the operation of setting the property value. The corresponding reflection API method is Reflect.set()
const test2={} const proxy2=new Proxy(test2,{ set(target,property,value,receiver){ console.log("Already called set()") const res=Reflect.set(...arguments); console.log(res);// true return res } }) proxy2.name='yihen';// set() has already been called console.log(test2.name); //yihen
-
Return value
Return true to indicate success; Returning false means failure. TypeError will be thrown in strict mode -
Intercept operation
- proxy.property=value;
- proxy[property]=value;
- Object.create(proxy)[value];
- Reflect.set(taget,property,value,receiver)
- Catcher handler parameters
- Target: target object
- Property: the string key property on the referenced target object
- Value: the value to assign to the attribute
- receiver: the object that receives the initial assignment
- Catcher invariant
-
If target.property is not writable and configurable, the property value of the target cannot be modified
-
If the target.property is not configurable and the [[Set]] attribute is undefined, the value of the target property cannot be modified. In strict mode, the handler will throw a TypeError if it returns false
has()
The has() catcher will be called in the in operator, and the corresponding reflection API method is Reflect.has();
/* has() */ const test3={} const proxy3=new Proxy(test3,{ has(target,property){ console.log("You called has()") return Reflect.has(...arguments) } }) console.log("name" in proxy3);// false proxy3.name='yihen' console.log("name" in proxy3);// true
-
Return value
has() must return a bool value, indicating whether the attribute exists. The returned non bool value will be converted to a bool value -
Intercept operation
- property in proxy
- property in Object.create(proxy)
- with(proxy){(property);}
- Reflect.has(proxy,property)
- Catcher handler parameters
- Target: target object
- Property: the string key property on the referenced target object
- Catcher invariant
-
If target.property exists and is not configurable, the handler must return true
-
If target.property exists and the target object is not extensible, the handler must return true
defineProperty
The defineProperty() catcher is called in Object.defineProperty(). The corresponding reflection API method is Reflect.defineProperty()
/* defineProperty() */ const test4={} const proxy4=new Proxy(test4,{ defineProperty(target,property,descriptor){ console.log('You called defineProperty'); return Reflect.defineProperty(...arguments) } }); Object.defineProperty(proxy4,'name',{ value:'yihen' });//You called defineProperty
- Return value
defineProperty() must return a bool value indicating whether the property was successfully defined. Returned non bool values are converted to bool values
- Intercept operation
- Object.defineProperty(proxy,property,descriptor)
- Reflect.defineProperty(proxy,property,descriptor)
- Catcher handler parameters
- Target: target object
- Property: the string key property on the referenced target object
- descriptor: an object that contains optional enumerable, configurable, writable, value, get, and set definitions
- Catcher invariant
- Properties cannot be defined if the target object is not extensible
- If the target object has a configurable property, you cannot add a non configurable property with the same name
- If the target object has a non configurable property, you cannot add a configurable property with the same name
getOwnPropertyDescriptor()
The getOwnPropertyDescriptor() catcher will be called in Object.getOwnPropertyDescriptor(). The corresponding reflection API method is Reflect.getOwnPropertyDescriptor()
/* getOwnPropertyDescriptor() */ const test5={name:'yihen'} const proxy5=new Proxy(test5,{ getOwnPropertyDescriptor(target,property){ console.log('You called getOwnPropertyDescriptor') return Reflect.getOwnPropertyDescriptor(...arguments) } }) const res= Object.getOwnPropertyDescriptor(proxy5,'name') // 'you called getOwnPropertyDescriptor' console.log(res) /* { value: 'yihen', writable: true, enumerable: true, configurable: true } */
-
Return value
getOwnPropertyDescriptor() must return an object or undefined if the property does not exist -
Intercepted operation
- Object.getOwnpropertyDescriptor(proxy,property)
- Reflect.getOwnPropertyDescriptor(proxy,property)
- Catcher handler parameters
- Target: target object
- Property: the string key property on the referenced target object
- Invariant of catcher
-
If its own target.property exists and is not configurable, the handler must return an object indicating the existence of the property
-
If its own target.property exists and can be configured, the handler must return an object indicating that the property exists and can be configured
-
If target.property does not exist and target is not extensible, the handler must return undefined to indicate that the property does not exist
-
If target.property does not exist, the handler cannot return an object indicating that the property is configurable
deleteProperty()
The deleteproperty () catcher is called in the delete operator. The corresponding reflection API method is Reflect.deleteProperty().
/* deleteProperty() */ const test6={name:'yihen'} const proxy6=new Proxy(test6,{ deleteProperty(target,property){ console.log('You called deleteProperty()') return Reflect.deleteProperty(...arguments) } }) console.log(proxy6.name);// yihen delete proxy6.name; console.log(proxy6.name);// undefined
- Return value
The return value of deleteProperty() must be a bool value, indicating whether the property is deleted successfully. Returned non bool values are converted to bool values
- Intercept operation
- delete proxy.property
- delete proxy[property]
- Reflect.deleteProperty(proxy,property)
- Catcher handler parameters
- Target: target object
- Property: the string key property on the referenced target object
- Catcher invariant
If the self owned target.property is not configurable, the processing function cannot delete this property
ownKeys()
The onwKeys() catcher will be called in Object.keys() and similar methods. The corresponding reflection API method is Reflect.ownKeys()
/* ownKeys() */ const test7={name:'yihen',age:18} Object.defineProperty(test7,'id',{ value:12345678 }) const proxy7=new Proxy(test7,{ ownKeys(target){ console.log('You called ownKeys()') const res=Reflect.ownKeys(...arguments) console.log(res);// [ 'name', 'age','id ] return res } }) const res2=Object.keys(proxy7) console.log(res2);// [ 'name', 'age' ]
- Return value
ownKeys() must return an enumerable object containing a string or symbol
- Intercepted operation
- Object.getOwnPropertyNames(proxy);
- Object.getOwnPropertySymbols(proxy);
- Object.keys(proxy);
- Reflect.ownKeys(proxy)
- Catcher handler parameters
Target: target object
- Catcher invariant
- The returned enumerable object must contain all non configurable own properties of target
- If the target is not extensible, the returned enumerable object must accurately contain its own attribute key
getPrototypeOf()
The getPrototypeOf() catcher will be called in Object.getPrototypeOf(). The corresponding reflection API method is Reflect.getPrototypeOf().
/* getPrototypeOf() */ const test8={} const proxy8=new Proxy(test8,{ getPrototypeOf(target){ console.log("You called getPrototypeOf()") const res=Reflect.getPrototypeOf(...arguments); console.log(res);//[Object: null prototype] {} return res } }) console.log(Object.getPrototypeOf(proxy8));//[Object: null prototype] {}
- Return value
getPrototypeOf() must return an object or null
- Intercepted operation
- Object.getPrototypeOf(proxy);
- proxy.__proro__
- Object.prototypeOf.isPrototypeOf(proxy)
- proxy instanceof Object
- Reflect.getPrototypeOf(proxy)
- Capture handler parameters
- Target: target object
- Capture invariant
If the target is not extensible, the only valid return value of Object.getPrototype(proxy) is the return value of Object.getPrototypeOf(target)
setPrototypeOf()
The setPrototypeOf() catcher will be called in Object.setPrototypeOf(), and the corresponding reflection API method is Reflect.setPrototypeOf()
/* setPrototypeOf() */ const test9={} const proxy9=new Proxy(test9,{ setPrototypeOf(target,property){ console.log('You called setPrototypeOf()') const res=Reflect.setPrototypeOf(...arguments); console.log(res); // true return res } }) Object.setPrototypeOf(proxy9,Object);
- Return value
setPrototypeOf() must return bool value, indicating whether the prototype assignment is successful. The returned non bool value will be converted to bool value
- Intercepted operation
- Object.setPrototypeOf(proxy)
- Reflect.setPrototypeOf(proxy)
- Catcher handler parameters
- Target: target object
- Prototype: substitute prototype of target. null if it is a top-level prototype
- Catcher infinitive
If the target is not extensible, the only valid prototype parameter is Object.getPrototypeOf(target)
isExtensible()
The isExtensible() catcher is called in Object.isExtensible(). The corresponding reflection API method is Reflect.isExtensible().
const test1={} const proxy1=new Proxy(test1,{ isExtensible(target){ console.log("Calling isExtensible()"); const res=Reflect.isExtensible(...arguments); console.log(res);// true return res } }) console.log(Object.isExtensible(proxy1));//true
-
Return value
isExtensible() must return a bool value indicating whether the target is extensible. Returned non bool values are converted to bool values. -
Intercepted operation
- Object.isExtensible(proxy)
- Reflect.isExtensible(proxy)
- Capture handler parameters
- Target: target object
- Catcher invariant
- If the target is extensible, it must return true
- If the target is not extensible, false must be returned
preventExtensions()
The preventExtensions() catcher is called in Object.preventExtensions(). The corresponding reflection API method is Reflect.preventExtensions()
/* preventExtensions() */ const test2={} const proxy2=new Proxy(test2,{ preventExtensions(target){ console.log('You called preventExtensions()') const res=Reflect.preventExtensions(...arguments) console.log(res);// true return res } }) console.log(Object.preventExtensions(proxy2));// {}
- Return value
preventExtensions() must return a bool value, indicating whether the target should not be extensible. The returned non bool value will be converted to a bool value
- Intercepted operation
- Object.preventExtensions(proxy)
- Reflect.preventExtensions(proxy)
- Catcher handler operation
target; Target object
- Capture its invariants
If Object.isExtensible(proxy) is false, the handler must return true
apply
The apply () catcher is called when the function is called. The corresponding reflection API method is Reflect.apply()
/* apply() */ const test3=()=>{} const proxy3=new Proxy(test3,{ apply(target,thisArg,...argumentsList){ console.log('You called apply()') const res=Reflect.apply(...arguments) console.log(res);// undefined return res } }) proxy3()
- Return value
Unlimited return value
- Intercepted operation
- proxy(...arguments)
- Function.prototype.apply(thisArg,argumentsList)
- Function.prototype.call(thisArg,...argumentsList)
- Reflect.apply(target,thisArg,argumentsList)
- Catcher handler parameters
- Target: target object
- thisArg: this parameter when calling the function
- argumentsList: list of arguments when calling a function
- Catcher invariant
- target must be a function object
construct()
The construct () catcher is called in the new operator. The corresponding reflection API method is Reflect.construct()
/* construct() */ const test4=function(){} const proxy4=new Proxy(test4,{ construct(target,argumentsList,newTarget){ console.log('You called construct()'); const res=Reflect.construct(...arguments) console.log(res);//test4 {} return res } }) new proxy4;
- Return value
construct() must return an object
- Intercept operation
- new proxy(...argumentsList)
- Reflect.construct(target,argumentsList,newTarget)
- Catcher handler parameters
- Target: target constructor
- argumentsList: the list of arguments passed to the target constructor
- newTarget: constructor originally called
- Catcher invariant
target must be available as a constructor