当前位置:网站首页>Proxy and reflection (II)
Proxy and reflection (II)
2022-06-12 02:11:00 【Red blue purple】
Proxy and reflection ( Two )
There are some useful functions that can be implemented using the proxy pattern .
Capture operation
By adding a corresponding catcher , You can capture it get、set、has Wait for the operation , You can monitor when and where this object has been accessed , And can access 、 Do what you want to do before revision , And realize the original function again through reflection .
const user = {
name: 'clz'
}
const proxy = new Proxy(user, {
get(target, property, receiver) {
console.log(` visit ${
property}`)
return Reflect.get(...arguments)
},
set(target, property, value, receiver) {
console.log(` Set up ${
property}=${
value}`)
return Reflect.set(...arguments)
}
})
console.log(proxy.name)
proxy.age = 21

Here's a little bit of attention : The operation through the proxy object will be captured , Operations that directly manipulate the target object are not captured .
const user = {
name: 'clz'
}
const proxy = new Proxy(user, {
get(target, property, receiver) {
console.log(` visit ${
property}`)
return Reflect.get(...arguments)
}
})
console.log(proxy.name)
console.log(user.name)

Hidden attribute
Because the internal implementation of the proxy is invisible to the external code , So it is easy to hide the attributes on the target object . We said that above , The original function needs to be realized through reflection , But we can also not realize the original function , Instead, it returns other values .
const user = {
name: 'clz',
age: 21
};
const proxy = new Proxy(user, {
get(target, property, receiver) {
if (property === 'name') {
// hide name attribute
return undefined;
}
return Reflect.get(...arguments)
}
});
console.log(user)
console.log(user.name)
console.log(user.age)
console.log('%c%s', 'font-size:24px;color:red', '=================')
console.log(proxy)
console.log(proxy.name)
console.log(proxy.age)

From above , We can know , Direct access to the target object 、 Target object properties and access to proxy objects can achieve the same results . however , Access... Through a proxy name Property will get undefined, Because we have hidden attributes in the capture operation .
verification
Attribute validation
Because all assignment operations will trigger set Catcher , Therefore, you can decide whether to allow or reject the assignment according to the assigned value , Not verified , direct return false The assignment can be rejected .
const user = {
name: 'clz',
age: 21
};
const proxy = new Proxy(user, {
set(target, property, value) {
if (typeof value !== 'number') {
console.log(' No number type , Reject assignment ')
return false;
} else {
return Reflect.set(...arguments);
}
}
});
proxy.age = 999;
console.log(proxy.age);
proxy.age = '111';
console.log(proxy.age);

When we return false when , That is, it fails to pass the verification , You can avoid the implementation of the original behavior ,
Function parameter validation
Similar to validating object properties , You can also review the parameters of a function .
First , Functions can also use proxies .apply The catcher is called when the function is called .
function fn() {
}
const proxy = new Proxy(fn, {
apply() {
console.log(' Call function ')
}
});
proxy(1, 2, 3, 4, 5)
So we should apply Operation verification in the catcher .
function mysort(...nums) {
return nums.sort((a, b) => a - b);
}
// stay `apply` Parameter validation in the catcher
const proxy = new Proxy(mysort, {
apply(target, thisArg, argumentsList) {
// target: Target audience
// thisArg: When calling a function this Parameters
// argumentsList: List of parameters when calling a function
for (const arg of argumentsList) {
if (typeof arg !== 'number') {
throw ' Function arguments must be number';
}
}
return Reflect.apply(...arguments);
}
});
let fin = proxy(2, 1, 6, 3, 4, 3);
console.log(fin);
fin = proxy(2, 1, 'hello', 3, 4, 3);
console.log(fin);
The same goes for constructors , Only the constructor is passed through constructor Capture to implement the proxy .
function Person(name) {
this.name = name
}
const proxy = new Proxy(Person, {
construct() {
console.log(123)
return Reflect.construct(...arguments)
}
});
const p = new proxy('clz')
console.log(p)
Data binding
Through the agent, the irrelevant parts of the original operation can be linked together .
Example : Bind the proxied class to a global collection of instances , Add all the created instances to this collection .`
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('clz')
new proxy('czh')
console.log(userList)
Event distributor
Before we start , Let's start with a little question .
const nums = []
const proxy = new Proxy(nums, {
set(target, property, value, receiver) {
console.log('setting')
return Reflect.set(...arguments)
}
})
proxy.push(1)
The above code will be printed twice setting.
Why is that ?
Let's print out the attributes of each round of modification , Look at the .
const nums = []
const proxy = new Proxy(nums, {
set(target, property, value, receiver) {
console.log('setting')
console.log(property)
return Reflect.set(...arguments)
}
})
proxy.push(1)

We can find out , The first is 0, The second, length. in other words ,push It is actually divided into two stages , In the first round, modify the array first , The second round is to modify the array length , So it prints two rounds .( There is no authoritative explanation , The conclusion of the practical test , There are questions to comment on )
Back to the point : You can bind a collection to an event distributor , Each time a new instance is inserted , Will send messages .
const nums = []
function emit(newValue) {
console.log(' There's new data , The new data is ', newValue)
}
const proxy = new Proxy(nums, {
set(target, property, value, receiver) {
const result = Reflect.set(...arguments)
// Reflect.set return boolean value , This value indicates whether the property has been successfully set
if (result) {
// If it is set successfully , Call the event dispatch function , Pass the newly inserted value as a parameter
emit(Reflect.get(target, property, receiver))
}
return result
}
})
proxy.push(111)
proxy.push(222)
console.log(proxy)

You can find it here , We push Two pieces of data , But it will trigger the event distributor 4 Time , Why is that ?
This is what was said in this section ,push It is actually divided into two stages , In the first round, modify the array first , The second round is to modify the array length .
therefore , We should not just judge whether it has been successfully set up , You should also judge whether the attribute is length.
if (result && property !== 'length') {
// If it is set successfully , Call the event dispatch function , Pass the newly inserted value as a parameter
emit(Reflect.get(target, property, receiver))
}

边栏推荐
- 力扣解法汇总905-按奇偶排序数组
- Force deduction solution summary 668- the smallest number k in the multiplication table
- Database
- Force deduction solution summary 449 serialization and deserialization binary search tree
- leetcode:6. Zigzag transformation
- C asynchronous programming from simple to deep (III) details awaiter
- 2022最全面的Redis事务控制(带图讲解)
- 力扣解法汇总358-迷你语法分析器
- 力扣解法汇总-剑指 Offer II 114. 外星文字典
- 通用树形结构的迭代与组合模式实现方案
猜你喜欢

Ozzanmation action system based on SSE

leetcodeSQL:612. Nearest distance on plane

BaseDexClassLoader那些事

UE4\UE5触摸屏touch事件:单指、双指

How to stop anti-virus software from blocking a web page? Take gdata as an example

Smartbi helps you solve the problem of losing high-value customers

How to maximize the use of various matching methods—— Google SEM

How should programmers solve the problem of buying vegetables? Take you hand in hand to quickly order and grab vegetables by using the barrier free auxiliary function

ACL 2022 | 预训练语言模型和图文模型的强强联合

阿里云oss文件上传系统
随机推荐
Linux(CentOS6)安装MySQL5.5版本数据库
Summary of concrete (ground + wall) + Mountain crack data set (classification and target detection)
leetcodeSQL:612. Nearest distance on plane
力扣解法汇总905-按奇偶排序数组
Add sequence number column to MySQL query result set
PHP builds a high-performance API architecture based on sw-x framework (III)
Xcall cluster script (view JPS command)
Metaverse × How will smart cities develop?
MySQL table common operation mind map
Database
Leetcode 1005 maximized array sum after K negations
力扣解法汇总388-文件的最长绝对路径
Force deduction solution summary 713- subarray with product less than k
“中国东信杯”广西大学第四届程序设计竞赛(同步赛)
力扣解法汇总433-最小基因变化
[adjustment] notice on the opening of the 2022 pre adjustment system for postgraduate enrollment of Shanghai Second University of Technology
C language programming classic games - minesweeping
力扣解法汇总427-建立四叉树
BaseDexClassLoader那些事
Swiftyjson parsing local JSON files