当前位置:网站首页>Proxy and reflection
Proxy and reflection
2022-06-12 20:12:00 【Flying Behemoth】
《JavaScript Advanced programming 》 Reading notes
Basis of agency
Create an empty proxy
const target = {
id: 'target'
};
const handler = {};
const proxy = new Proxy(target, handler);Revocable agent
revoke Undo function is idempotent .
const target = {
id: 'target'
};
const handle = {
get() {
return 'iiiiiii';
}
}
const {proxy, revoke} = Proxy.revocable(target, handle);
revoke();
Practical reflection API
Reflection method uses object control and operation with granularity
- Reflection API Not limited to capture handlers
- Most reflections API Method in Object There are corresponding methods on the type
1. Status mark
Many reflection methods return Boolean values called status tags , Indicates whether the intended operation is successful .
const o = {}
try {
Object.defineProperty(o, 'foo', 'bar');
console.log('success');
} catch(e) {
console.log('fail');
}
// After refactoring
if(Reflect.defineProperty(o, 'foo', {value:'bar'})) {
console.log('success');
}else {
console.log('fail');
}The following reflection methods provide status markers :
- Reflect.defineProperty()
- Reflect.preventExtensions()
- Reflect.setPrototypeOf()
- Reflect.set()
- Reflect.deleteProperty()
2. Replace the operator with a first-order function
The following reflection methods provide operations that can only be done by operators
- Reflect.get() You can override the object property access operator
- Reflect.set() Can replace = Assignment operator
- Reflect.has() Can replace in Operator or with()
- Reflect.deleteProperty() Can replace delete The operator
- Reflect.constructor() Can replace new The operator
3. Safely apply functions
Through apply Method calls the function , The called function may also define its own apply attribute ( It's a long shot ). To get around this problem , as follows :
// Method 1 : Use definition in Function Archetype apply Method
Function.prototype.apply.call(myFunc, thisVal, argumentList);
// Method 2
Reflect.apply(myFunc, thisVal, argumentList);Acting for another agent
Build a multi-layer interception network on a target object
const target = {
id: 'target'
};
const firstProxy = new Proxy(target, {
get() {
console.log('first Proxy');
return Reflect.get(...arguments);
}
});
const secondProxy = new Proxy(firstProxy, {
get() {
console.log('second Proxy');
return Reflect.get(...arguments);
}
});
console.log(secondProxy.id);
// second Proxy
// first Proxy
// targetProblems and shortcomings of agency
- In the agency this
- Agent and internal slot
Proxy traps and reflection methods
get()
get() The catcher is called in the operation to get the property value . Corresponding reflection API by Reflect.get()
const myTarget = {};
const proxy = new Proxy(myTarget, {
get(target, property, receiver) {
console.log('get()');
return Reflect.get(...arguments);
}
});
proxy.foo; // get()- Return value : The return value is unlimited
- Intercept operation
- proxy.property
- proxy[property]
- Object.create(proxy)[property]
- Reflect.get(proxy, property, receiver)
- Catcher handler parameters
- target: Target audience
- property: String key property on the referenced target object
- receiver: Proxy objects or objects that inherit proxy objects
- The catcher invariant
If target.property Not writable and not configurable , The value returned by the handler must be the same as target.property matching .
If target.property Not configurable and [[Get]] Features for undefined, The return value of the handler must be undefined
set()
set() The catcher will be called in the operation of setting the property value . Corresponding reflection API by Reflect.set()
const myTarget = {};
const proxy = new Proxy(myTarget, {
set(target, property, value, receiver) {
console.log('set()');
return Reflect.set(...arguments)
}
});
proxy.foo = 'bar';
// set()- Return value : return true It means success ; return false It means failure , Throw in strict mode TypeError.
- Intercept operation
- proxy.property = value
- proxy[property] = value
- Object.create(proxy)[property] = value
- Reflect.set(proxy, property, receiver)
- Catcher handler parameters
- target: Target audience
- property: String key property on the referenced target object
- value: The value to assign to the attribute
- receiver: Receive the object originally assigned
- The catcher invariant
If target.property Not writable and not configurable , The value of the target attribute cannot be modified .
If target.property Not configurable and [[Set]] Features for undefined, The value of the target attribute cannot be modified .
has()
If target.property Not configurable and [[Set]] Features for undefined, The value of the target attribute cannot be modified .
const myTarget = {};
const proxy = new Proxy(myTarget, {
has(target, property) {
console.log('has()');
return Reflect.has(...arguments)
}
});
'foo' in proxy;
// has()- Return value : Must return a Boolean value , Indicates whether the attribute exists . Returning non Boolean values will be transformed into Boolean values
- Intercept operation
- property in proxy
- property in Object.create(proxy)
- with(proxy) {(property);}
- Reflect.has(proxy, property)
- Catcher handler parameters
- target: Target audience
- property: String key property on the referenced target object
- The 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()
defineProperty() The catcher will be in Object.defineProperty() In the called . Corresponding reflection API Method is
Reflect.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()- Return value : Must return a Boolean value , Indicates whether the attribute was successfully defined . Returning non Boolean values will be transformed into Boolean values .
- Intercept operation
- Object.defineProperty(proxy, property, descriptor)
- Reflect.defineProperty(proxy, property, descriptor)
- Catcher handler parameters
- target: Target audience
- property: String key property on the referenced target object
- descriptor: Contains optional enumerable、 configurable、 writable、 value、 get and set
Defined objects .
- The catcher invariant
If the target object is not extensible , You cannot define the attribute .
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()
getOwnPropertyDescriptor() The catcher will be in Object.getOwnPropertyDescriptor() In the called . Corresponding reflection API Method is Reflect.getOwnPropertyDescriptor()
const myTarget = {};
const proxy = new Proxy(myTarget, {
getOwnPropertyDescriptor(target, property) {
console.log('getOwnPropertyDescriptor()');
return Reflect.getOwnPropertyDescriptor(...arguments)
}
});
Object.getOwnPropertyDescriptor(proxy, 'foo');
// getOwnPropertyDescriptor()- Return value : Must return object , Or return... When the property does not exist undefined.
- Intercept operation
- Object.getOwnPropertyDescriptor(proxy, property)
- Reflect.getOwnPropertyDescriptor(proxy, property)
- Catcher handler parameters
- target: Target audience
- property: String key property on the referenced target object
- The catcher invariant
If you have your own target.property Exists and is not configurable , The handler must return a that indicates the existence of the property
object .
If you have your own target.property Existing and configurable , Then the handler must return an object that represents the configurable property .
If you have your own target.property Exist and target Non scalable , Then the handler must return a value indicating that the property exists
The object in .
If target.property Does not exist and target Non scalable , The handler must return undefined Denotes the genus
Sex does not exist .
If target.property non-existent , The handler cannot return an object that represents that the property is configurable .
deleteProperty()
deleteProperty() The catcher will be in delete Called in the operator . Corresponding reflection API Method is Reflect.
deleteProperty().
const myTarget = {};
const proxy = new Proxy(myTarget, {
deleteProperty(target, property) {
console.log('deleteProperty()');
return Reflect.deleteProperty(...arguments)
}
});
delete proxy.foo
// deleteProperty()- Return value : Must return a Boolean value , Indicates whether the attribute is deleted successfully . Returning non Boolean values will be transformed into Boolean values .
- Intercept operation
- delete proxy.property
- delete proxy[property]
- Reflect.deleteProperty(proxy, property)
- Catcher handler parameters
- target: Target audience
- property: String key property on the referenced target object
- The catcher invariant
If you have your own target.property Exists and is not configurable , Then the handler cannot delete this property .
ownKeys()
ownKeys() The catcher will be in Object.keys() And similar methods . Corresponding reflection API Method is Reflect.
ownKeys().
const myTarget = {};
const proxy = new Proxy(myTarget, {
ownKeys(target) {
console.log('ownKeys()');
return Reflect.ownKeys(...arguments)
}
});
Object.keys(proxy);
// ownKeys()- Return value : An enumerable object containing a string or symbol must be returned .
- Intercept operation
- Object.getOwnPropertyNames(proxy)
- Object.getOwnPropertySymbols(proxy)
- Object.keys(proxy)
- Reflect.ownKeys(proxy)
- Catcher handler parameters
- target: Target audience
- The catcher invariant
The returned enumerable object must contain target All non configurable self owned properties of .
If target Non scalable , The returned enumerable object must accurately contain its own property key
getPrototypeOf()
getPrototypeOf() The catcher will be in Object.getPrototypeOf() In the called . Corresponding reflection API Method is
Reflect.getPrototypeOf()
const myTarget = {};
const proxy = new Proxy(myTarget, {
getPrototypeOf(target) {
console.log('getPrototypeOf()');
return Reflect.getPrototypeOf(...arguments)
}
});
Object.getPrototypeOf(proxy);
// getPrototypeOf()- Return value : You must return an object or null
- Intercept operation
- Object.getPrototypeOf(proxy)
- Reflect.getPrototypeOf(proxy)
- proxy.__proto__
- Object.prototype.isPrototypeOf(proxy)
- proxy instanceof Object
- Catcher handler parameters
- target: Target audience
- The catcher invariant
If target Non scalable , be Object.getPrototypeOf(proxy) The only valid return value is Object.
getPrototypeOf(target) The return value of .
setPrototypeOf()
setPrototypeOf() The catcher will be in Object.setPrototypeOf() In the called . Corresponding reflection API Method is
Reflect.setPrototypeOf().
const myTarget = {};
const proxy = new Proxy(myTarget, {
setPrototypeOf(target, prototype) {
console.log('setPrototypeOf()');
return Reflect.setPrototypeOf(...arguments)
}
});
Object.setPrototypeOf(proxy, Object);
// setPrototypeOf()- Return value : Must return a Boolean value , Indicates whether the prototype assignment is successful . Returning non Boolean values will be transformed into Boolean values .
- Intercept operation
- Object.setPrototypeOf(proxy)
- Reflect.setPrototypeOf(proxy)
- Catcher handler parameters
- target: Target audience
- prototype: target Alternative prototypes , If it is a top-level prototype, it is null.
- The catcher invariant
If target Non scalable , Only valid prototype The parameter is Object.getPrototypeOf(target)
The return value of .
isExtensible()
isExtensible() The catcher will be in Object.isExtensible() In the called . Corresponding reflection API Method is
Reflect.isExtensible().
const proxy = new Proxy(myTarget, {
isExtensible(target) {
console.log('isExtensible()');
return Reflect.isExtensible(...arguments)
}
});
Object.isExtensible(proxy);
// isExtensible()- Return value : Must return a Boolean value , Express target Is it extensible . Returning non Boolean values will be transformed into Boolean values .
- Intercept operation
- Object.isExtensible(proxy)
- Reflect.isExtensible(proxy)
- Catcher handler parameters
- target: Target audience
- The catcher invariant
If target Scalable , The handler must return true.
If target Non scalable , The handler must return false.
preventExtensions()
preventExtensions() The catcher will be in Object.preventExtensions() In the called . Corresponding reflection API
Method is Reflect.preventExtensions().
const myTarget = {};
const proxy = new Proxy(myTarget, {
preventExtensions(target) {
console.log('preventExtensions()');
return Reflect.preventExtensions(...arguments)
}
});
Object.preventExtensions(proxy);
// preventExtensions()- Return value : Must return a Boolean value , Express target Is it already non extensible . Returning non Boolean values will be transformed into Boolean values .
- Intercept operation
- Object.preventExtensions(proxy)
- Reflect.preventExtensions(proxy)
- Catcher handler parameters
- target: Target audience
- The catcher invariant
If Object.isExtensible(proxy) yes false, The handler must return true.
apply()
apply() The catcher is called when the function is called . Corresponding reflection API Method is Reflect.apply().
const myTarget = () => {};
const proxy = new Proxy(myTarget, {
apply(target, thisArg, ...argumentsList) {
console.log('apply()');
return Reflect.apply(...arguments)
}
});
proxy();
// apply()- Return value : The return value is unlimited .
- Intercept operation
- proxy(...argumentsList)
- Function.prototype.apply(thisArg, argumentsList)
- Function.prototype.call(thisArg, ...argumentsList)
- Reflect.apply(target, thisArgument, argumentsList
- Catcher handler parameters
- target: Target audience .
- thisArg: When calling a function this Parameters .
- argumentsList: List of parameters when calling a function
- The catcher invariant
target: Must be a function object .
construct()
construct() The catcher will be in new Called in the operator . Corresponding reflection API Method is Reflect.construct().
const myTarget = function() {};
const proxy = new Proxy(myTarget, {
construct(target, argumentsList, newTarget) {
console.log('construct()');
return Reflect.construct(...arguments)
}
});
new proxy;
// construct()- Return value : An object must be returned .
- Intercept operation
- new proxy(...argumentsList)
- Reflect.construct(target, argumentsList, newTarget)
- Catcher handler parameters
- target: Target constructor .
- argumentsList: The list of parameters passed to the target constructor .
- newTarget: Constructor originally called .
- The catcher invariant
target Must be used as a constructor .
The proxy pattern
Trace attribute mode
Monitor when objects are accessed
const user = {
name: 'Jake'
};
const proxy = new Proxy(user, {
get(target, property, receiver) {
console.log(`Getting ${property}`);
return Reflect.get(...arguments);
},
set(target, property, value, receiver) {
console.log(`Setting ${property}=${value}`);
return Reflect.set(...arguments);
}
});
proxy.name; // Getting name
proxy.age = 27; // Setting age=27Hidden attribute
const hiddenProperties = ['foo', 'bar'];
const targetObject = {
foo: 1,
bar: 2,
baz: 3
};
const proxy = new Proxy(targetObject, {
get(target, property) {
if (hiddenProperties.includes(property)) {
return undefined;
} else {
return Reflect.get(...arguments);
}
},
has(target, property) {
if (hiddenProperties.includes(property)) {
return false;
} else {
return Reflect.has(...arguments);
}
}
});
// get()
console.log(proxy.foo); // undefined
console.log(proxy.bar); // undefined
console.log(proxy.baz); // 3
// has()
console.log('foo' in proxy); // false
console.log('bar' in proxy); // false
console.log('baz' in proxy); // trueAttribute validation
const target = {
onlyNumbersGoHere: 0
};
const proxy = new Proxy(target, {
set(target, property, value) {
if (typeof value !== 'number') {
return false;
} else {
return Reflect.set(...arguments);
}
}
});
proxy.onlyNumbersGoHere = 1;
console.log(proxy.onlyNumbersGoHere); // 1
proxy.onlyNumbersGoHere = '2';
console.log(proxy.onlyNumbersGoHere); // 1Function and constructor parameter validation
function median(...nums) {
return nums.sort()[Math.floor(nums.length / 2)];
}
const proxy = new Proxy(median, {
apply(target, thisArg, argumentsList) {
for (const arg of argumentsList) {
if (typeof arg !== 'number') {
throw 'Non-number argument provided';
}
}
return Reflect.apply(...arguments);
}
});
console.log(proxy(4, 7, 1)); // 4
console.log(proxy(4, '7', 1));
// Error: Non-number argument provided
Similarly , You can require that you must pass arguments to the constructor when instantiating :
class User {
constructor(id) {
this.id_ = id;
}
}
const proxy = new Proxy(User, {
construct(target, argumentsList, newTarget) {
if (argumentsList[0] === undefined) {
throw 'User cannot be instantiated without id';
} else {
return Reflect.construct(...arguments);
}
}
});
new proxy(1);
new proxy();
// Error: User cannot be instantiated without idData binding to objects
const userList = [];
class User {
constructor(name) {
this.name_ = name;
}
}
const proxy = new Proxy(User, {
construct() {
const newUser = Reflect.construct(...arguments);
userList.push(newUser);
return newUser;
}
});
new proxy('John');
new proxy('Jacob');
new proxy('Jingleheimerschmidt');
console.log(userList); // [User {}, User {}, User{}]const userList = [];
function emit(newValue) {
console.log(newValue);
}
const proxy = new Proxy(userList, {
set(target, property, value, receiver) {
const result = Reflect.set(...arguments);
if (result) {
emit(Reflect.get(target, property, receiver));
}
return result;
}
});
proxy.push('John');
// John
proxy.push('Jacob');
// Jacob边栏推荐
猜你喜欢

Viewpoint sharing | Li Wei, an expert of Gewu titanium intelligent technology products: underlying logic and scenario practice of unstructured data platform

Reading small program graduation design based on wechat e-book (5) assignment

【生成对抗网络学习 其三】BiGAN论文阅读笔记及其原理理解

Generate API documents using swagger (go language example)

The latest Ningxia construction safety officer simulation question bank and answers in 2022

Reading applet based on wechat e-book graduation design (2) applet function

Process accounting, process time, daemon

Niuke.com: sum of three numbers

测试必备:推荐一款跨平台App性能专项测试工具!

Parameter meaning of random forest randomforestclassifier in sklearn
随机推荐
Wechat e-book reading applet graduation design work (6) opening defense ppt
Macro definitions and functions
Understanding of data in memory
3 R complex data types
[generation confrontation network learning III] reading notes of Bigan paper and its principle understanding
What is a federated index?
const
JDBC接口总结
PostgreSQL数据库复制——后台一等公民进程WalReceiver pg_stat_wal_receiver视图
How mysterious is "PIP not an internal or external command, nor a runnable program or batch file"
Efcore tuning
Interpreter Files
Simple understanding of anti shake function
Parameter meaning of random forest randomforestclassifier in sklearn
牛客網:三數之和
Golang type assertion understanding [go language Bible]
Low code enables rural construction to open "smart mode"
1. Getting to know R
Kyma application connectivity feature introduction
【无标题】