当前位置:网站首页>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
// target
Problems 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=27
Hidden 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); // true
Attribute 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); // 1
Function 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 id
Data 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
边栏推荐
- Wall Street cheat sheet
- more-copy. JS specifies that the file template is generated to the specified file directory
- Demand and business model analysis-1-business model canvas
- 使用Swagger生成 API 文档(go语言示例)
- Deep feature synthesis and genetic feature generation, comparison of two automatic feature generation strategies
- MySQL installation and Application
- What is the difference between union and union all
- Wechat e-book reading applet graduation design works (1) development outline
- Reading small program graduation design based on wechat e-book (5) assignment
- Reading small programs based on wechat e-book graduation design works (7) Interim inspection report
猜你喜欢
Demand and business model analysis-2-business model types
3 R complex data types
exec函数、shell的实现
In 2022, 20 cities with the largest number of college students in China
How to make a computer installation and startup USB flash disk
Niuke.com: sum of three numbers
Torch network model is converted to onnx format and visualized
QT pro文件配置ffmpeg宏
Viewpoint sharing | Li Wei, an expert of Gewu titanium intelligent technology products: underlying logic and scenario practice of unstructured data platform
Detailed explanation of IO flow basic knowledge -- file and IO flow principle
随机推荐
If you master these skills, you can also write a high score resume in the eyes of HR
[leetcode 7 solution] integer inversion
Reading small programs based on wechat e-book graduation design works (7) Interim inspection report
Scalars, vectors, arrays, and matrices
Reading small program graduation design based on wechat e-book (5) assignment
How mysterious is "PIP not an internal or external command, nor a runnable program or batch file"
QT pro文件配置ffmpeg宏
Simple understanding of anti shake function
Wechat e-book reading applet graduation design completion works (8) graduation design thesis template
Demand and business model innovation-5-process
Demand and business model innovation - demand 1 - Introduction to demand engineering
The new colleague asked me what "where 1=1" means???
一致性哈希的简单认识
Blue Bridge Cup basic-14 VIP question time conversion
What is disk IO?
Alipay payment episode 11: monitoring after successful payment callback
A simple understanding of consistent hash
Installation and testing of open source deep learning framework plaidml
[leetcode] small thinking of optimal division
2022年,中国大学生最多的20个城市