Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of Proxy usage cases

2025-03-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains the "Proxy use case analysis", the article explains the content is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "Proxy use case analysis" bar!

An example of understanding the agent model

As a single straight steel programmer, Xiao Wang has recently fallen in love with the front-end sister, but he is not familiar with the front-end sister, so he decided to entrust UI, who is familiar with the front-end sister, to help him build bridges and lead lines. Xiao Wang then invited the little sister UI to have a big dinner, and then took out a love letter to entrust it to the little sister at the front desk. I like you, and I want to sleep with you, worthy of a straight man of steel. But it must be impossible to write like this. UI's little sister eats people with a short mouth, so she helped change the love letter so that I like you. I want to get up with you in the morning glow and give it to the little sister at the front desk. Although it is not clear whether the matchmaking was successful or not, this story tells us that Xiao Wang deserves a single dog.

In fact, the above is a more typical example of the agency model. Xiao Wang wants to send a love letter to the little sister at the front desk. Because he is not familiar with it, he entrusts the little sister UI, and the little sister UI is equivalent to an agent to complete the love letter delivery in place of Xiao Wang.

Extension

Using the above example, let's consider the data response principle of Vue, such as the following code

Const xiaowang = {love:'I like you, I want to sleep with you'} / / send the little sister a love letter function sendToMyLove (obj) {console.log (obj.love) return 'rascal, roll'} console.log (sendToMyLove (xiaowang))

If there is no UI little sister instead of sending a love letter, it shows that the ending is tragic. Think of the two-way binding of Vue2.0, which is realized by the property get,set method monitored by Object.defineProperty. This Object.defineProperty is equivalent to the little sister UI.

Const xiaowang = {loveLetter:'I like you, I want to sleep with you'} / / UI little sister agent Object.defineProperty (xiaowang,'love', {get () {return xiaowang.loveLetter.replace ('sleep', 'get up together in the morning glow')}) / / send a love letter to the little sister function sendToMyLove (obj) {console.log (obj.love) return'is still quite poetic, but I don't like it. Roll'} console.log (sendToMyLove (xiaowang))

Although it is still a sad story, because the success rate of sending Mercedes-Benz may be higher. But we can see that Object.defineproperty allows you to intercept existing properties of an object and then do some additional operations.

Existing problems

In Vue2.0, data bi-directional binding is to listen to every property of the object through Object.defineProperty, and then publish the subscriber schema to achieve the data response in the get,set method, but there are some defects, such as only listening to existing attributes, but powerless to add and delete attributes, and unable to listen for changes in the array, so it is replaced by a more powerful Proxy in Vue3.0.

(recommended tutorial: Vue 2 tutorial)

Learn about Proxy

Proxy is a new feature of ES6, which can be used to intercept methods of js operations, thus performing proxy operations on these methods.

Rewrite the above example with Proxy

For example, we can rewrite the above love letter plot through Proxy:

Const xiaowang = {loveLetter:'I like you I want to sleep with you'} const proxy = new Proxy (xiaowang, {get (target,key) {if (key = 'loveLetter') {return target [key]. Replace (' sleep', 'get up together in the morning glow')}) / / send a love letter to my little sister function sendToMyLove (obj) {console.log (obj.loveLetter) return'is still poetic, but I don't like it. Roll'} console.log (sendToMyLove (proxy)) look at such a scene again.

Please use Object.defineProperty and Proxy to refine the following code logic.

Function observe (obj, callback) {} const obj = observe ({name: 'Zijun', sex: 'male'}, (key, value) = > {console.log (the value of the `attribute [${key}] is modified to [${value}]`)}) / / after the execution of this code, the value of the output attribute [name] is changed to [girl] obj.name = 'girl' / after the code is executed The value of the output attribute [sex] is modified to [female] obj.name = 'female'

After reading the above code, I hope you can implement the following by yourself. below, we use Object.defineProperty and Proxy to implement the above logic.

Use Object.defineProperty

/ * Please implement this function Make the following code logic run properly * @ param {*} obj object * @ param {*} callback callback function * / function observe (obj, callback) {const newObj = {} Object.keys (obj) .forEach (key = > {Object.defineProperty (newObj, key, {configurable: true, enumerable: true, get () {return obj [key]}, / / when the value of the attribute is modified Set will be called At this point, you can call the callback function set (newVal) {obj [key] = newVal callback (key, newVal)}} in set) return newObj} const obj = observe ({name: 'Zijun', sex: 'male'}, (key) Value) = > {console.log (the value of the `attribute [${key}] is modified to [${value}]`)}) / / after this code is executed The value of the output attribute [name] is modified to [girl] obj.name = 'girl' / / after the code is executed, the value of the output attribute [sex] is changed to [female] obj.name = 'female'

Use Proxy

Function observe (obj, callback) {return new Proxy (obj, {get (target, key) {return target [key]}, set (target, key, value) {target [key] = value callback (key, value)}} const obj = observe ({name: 'Zijun', sex: 'male'}, (key) Value) = > {console.log (the value of the `attribute [${key}] is modified to [${value}]`)}) / / after this code is executed The value of the output attribute [name] is modified to [girl] obj.name = 'girl' / / after the code is executed, the value of the output attribute [sex] is changed to [female] obj.name = 'female'

Through the above two different implementations, we can get a general idea of the use of Object.defineProperty and Proxy, but when we add new properties to an object, the difference comes out, such as

/ / add programming website obj.gzh = 'W3C website'

You cannot listen for new properties with Object.defineProperty, but you can listen with Proxy. Comparing the above two pieces of code, we can see that there are the following differences

Object.defineProperty listens for every property of the object, while Proxy listens for the object itself.

Using Object.defineProperty requires traversing every property of the object, which has a certain impact on performance

New properties can also be monitored by Proxy, but not by Object.defineProperty.

A preliminary understanding of the concept and grammar of Proxy

In MDN, the Proxy is introduced like this: the Proxy object is used to define the custom behavior of basic operations (such as property lookups, assignments, enumerations, function calls, and so on). What do you mean? Proxy is like an interceptor. When reading the properties of an object, modifying its properties, getting a list of object properties, passing a for in loop, etc., it can intercept the default behavior on the object, and then customize these behaviors on its own. For example, set in the example above, we intercept the default set, and then add callback function calls to the custom set.

The syntax format of Proxy is as follows

/ * target: the object to be compatible can be an object, array, function, etc. * handler: it is an object that contains behavior functions that can listen on the object. For example, `get` and `set` * in the above example will return a new object proxy at the same time. In order to trigger the function in handler, you must use the return value to perform other operations, such as modifying the value * / const proxy = new Proxy (target, handler).

In the above example, we have used the get and set methods provided in handler, so let's take a look at the methods in handler.

List of methods in handler

The methods in handler can have the following thirteen methods, each of which corresponds to one or more operations against the proxy proxy object

Handler.get

When reading the properties in the object through proxy, it goes into the get hook function.

Handler.set

When you use proxy to set modified properties for an object, you will enter the set hook function

Handler.has

Has is triggered when in is used to determine whether the property is in the proxy proxy object, such as

Const obj = {name: 'Zijun'} console.log ('name' in obj)

Handler.deleteProperty

When you use delete to delete properties in an object, you will enter the deleteProperty` hook function

Handler.apply

When proxy listens to a function, when the function is called, it enters the apply hook function

Handle.ownKeys

When you use Object.getOwnPropertyNames,Object.getownPropertySymbols,Object.keys,Reflect.ownKeys to get the information of an object, you will enter the hook function ownKeys

Handler.construct

When you use the new operator, you enter the hook function construct

Handler.defineProperty

This hook function is entered when you use Object.defineProperty to modify the property modifier

Handler.getPrototypeOf

This hook function is entered when the prototype of the object is read

Handler.setPrototypeOf

When you set the prototype of the object, you enter this hook function

Handler.isExtensible

When you use Object.isExtensible to determine whether an object can add new properties, enter the hook function

Handler.preventExtensions

Enter the hook function when the object cannot be modified by setting new properties through Object.preventExtensions

Handler.getOwnPropertyDescriptor

Triggers the operation when getting the property description of a property of the proxy object, such as entering the hook function when executing Object.getOwnPropertyDescriptor (proxy, "foo")

Proxy provides 13 ways to intercept object operations. This article mainly selects some of the more important ones in Vue3 to explain. The rest of the suggestions can be read directly from MDN's introduction to Proxy.

Introduce get in detail

When reading the properties in the object through proxy, it goes into the get hook function.

The get hook function is triggered when we read properties from a proxy proxy. The structure of the get function is as follows

/ * target: target object, that is, the object proxied by proxy * key: the name of the attribute to be accessed * receiver: receiver is equivalent to the this of the attribute we want to read. In general, it is the proxy object itself. About the role of receiver, we will explain the example of * / handle.get (target,key, receiver) later.

We often need to encapsulate axios in our work. In the process of encapsulation, we also need to encapsulate the request exception. For example, different status codes return different exception information. Here are some status codes and their prompts:

/ / status code prompt const errorMessage = {400: 'error request', 401: 'system is not authorized, please log in again', 403: 'access denied', 404: 'request failed, the resource was not found'} / / usage const code = 404const message = errorMessage [code] console.log (message)

But there is a problem. There are many status codes, and it is impossible for us to enumerate every status code. So for some abnormal status codes, we hope to have a unified prompt. If the prompt is a system exception, please contact the administrator. At this time, you can use Proxy to handle the error message as an agent.

/ / status code prompt const errorMessage = {400: 'error request', 401: 'system is not authorized, please log in again', 403: 'access denied', 404: 'request failed, the resource was not found'} const proxy = new Proxy (errorMessage, {get (target,key) {const value = target [key] return value | | 'system exception Please contact administrator'}}) / / output error request console.log (proxy) / / output system exception, please contact administrator console.log (proxy) set

Set is triggered when a property in an object is assigned a value

When you assign a value to a property in an object, the set,set function is triggered with the following structure

/ * target: target object, that is, the object proxied by proxy * key: the name of the attribute to be assigned * value: the new value to be assigned to the target attribute * receiver: basically consistent with get's receiver * / handle.set (target,key,value, receiver) example

A system needs to input a series of values for data statistics, but when entering values, there may be some outliers. These outliers need to be dealt with when they are entered, such as values greater than 100 are converted to 100 and values less than 0 are converted to 0. At this time, proxy set can be used to process the data when assigning values.

Const numbers = [] const proxy = new Proxy (numbers, {set (target,key,value) {if (value)

< 0) { value = 0 }else if(value >

100) {value = 100} target [key] = value / / for set, true must be returned if the operation is successful, otherwise it will be regarded as a failure return true}}) proxy.push (1) proxy.push (101) proxy.push (- 10) / output [1,100,0] console.log (numbers) vs. Vue2.0

When using Vue2.0, if you add new properties to an object, you often need to call $set, because Object.defineProperty can only listen to existing properties, but the new properties cannot, and $set is equivalent to manually adding properties to the object, and then triggering the data response. But for Vue3.0, because of the use of Proxy, it is possible to listen for new properties in his set hook function, so $set is no longer needed

Const obj = {name: 'Zijun'} const proxy = new Proxy (obj, {set (target,key,value) {if (! target.hasOwnProperty (key)) {console.log (`added attribute ${key} with a value of ${value} `)} target [key] = value return true}}) / / added official account attribute / / added attribute gzh for output The value is front-end play proxy.gzh = 'front-end play' has

Has is triggered when in is used to determine whether the property is in the proxy proxy object.

/ * target: target object, that is, the object proxied through proxy * key: whether the key to be determined is in target * / handle.has (target,key) example

In general, when we declare a private attribute in js, we will start the name of the attribute with _. For these private attributes, there is no need for external calls, so if it can be hidden, it is best to use has to determine whether a property is in the object. If it starts with _, it returns false.

Const obj = {publicMethod () {}, _ privateMethod () {}} const proxy = new Proxy (obj, {has (target,key) {if (key.startsWith ('_')) {return false} return Reflect.get (target,key)}) / / output falseconsole.log ('_ privateMethod' in proxy) / / output trueconsole.log ('publicMethod' in proxy) deleteProperty

When you use delete to delete properties in an object, you will enter the deleteProperty` interceptor

/ * target: target object, that is, the object proxied through proxy * key: attribute to be deleted * / handle.deleteProperty (target,key) example

Now there is an object with user information, which can only be viewed but cannot be deleted or modified. Using Proxy, you can intercept attributes that cannot be deleted or modified and throw an exception, as follows

Const userInfo = {name: 'Zijun', gzh: 'have fun at the front end', sex: 'male', age: 22} / / only delete user name and official account const readonlyKeys = ['name',' gzh'] const proxy = new Proxy (userInfo, {set (target,key) Value) {if (readonlyKeys.includes (key)) {throw new Error (`attribute ${key} cannot be modified`)} target [key] = value return true}, deleteProperty (target Key) {if (readonlyKeys.includes (key)) {throw new Error (`attribute ${key} cannot be deleted`) return} delete target [key] return true}}) / / error delete proxy.name versus Vue2.0

In fact, similar to the problem solved by $set, Vue2.0 cannot listen to the deletion of attributes, so it provides $delete to delete attributes, but for Proxy, it is possible to listen for deletion operations, so you no longer need to use $delete

Other actions

In the above, we mentioned that Proxy's handler provides 13 functions. Above, we listed the three most commonly used functions. In fact, the usage of each of them is basically the same. For example, ownKeys, when you get the information about an object through Object.getOwnPropertyNames,Object.getownPropertySymbols,Object.keys,Reflect.ownKeys, you will enter the ownKeys hook function. With this, we can protect some attributes that we do not want to expose. For example, it is generally agreed that the attributes starting with _ are private attributes, so when you use Object.keys to get all the key of an object, you can block out all the attributes starting with _. For the remaining attributes, it is recommended that you take a look at the introduction in MDN.

Reflect

Above, we get the value of the property or modify the value of the property by directly manipulating the target, but in fact ES6 has provided us with an API to invoke the default behavior of the object within the Proxy, namely Reflect. For example, the following code

Const obj = {} const proxy = new Proxy (obj, {get (target,key,receiver) {return Reflect.get (target,key,receiver)}})

You may see that the above code is no different from using the target key directly, but in fact, the emergence of Reflect is to make the operation above Object more standardized. For example, we usually use in to determine whether a prop is in an object.

Const obj = {name: 'Zijun'} console.log ('name' in obj)

But the above operation is an imperative syntax, which can be transformed into a functional syntax through Reflect, which is more standardized.

Reflect.has (obj,'name')

In addition to has,get, in fact, Reflect provides a total of 13 static methods, these 13 static methods and Proxy handler above 13 methods are one-to-one correspondence, through the combination of Proxy and Reflect, you can intercept the default operation on the object, of course, this also belongs to the category of function metaprogramming.

Thank you for your reading, the above is the content of "Proxy use case analysis", after the study of this article, I believe you have a deeper understanding of the problem of Proxy use case analysis, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 216

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report