Proxy is a newly added built-in object in ES2015 (ES6) to customize some basic operations.
This article is my experience of getting method when learning Proxy.
As a newly defined built-in object in ES2015, Proxy can intercept and customize some basic operations of objects and functions, with high priority and convenience, allowing us to have an additional way to solve problems when writing code.
Proxy's get method is used to intercept read operations of object properties, such as obj.[key]. After setting the get method in the handler parameter of Proxy, the get method will be called first whenever a read operation is performed. We can intercept the read behavior in this method function. Please see the following code:
const obj = { key: 1 } const proxy = new Proxy(obj, { get: function(target, property, receiver) { ('get', property) return target[property] } }) () // get key // 1
There are three parameters of the get method: target is the object used when instantiating Proxy, in this example, obj; property is the property name you want to obtain in this read operation, in this example, key; the last parameter receiver is the instantiated Proxy itself, that is, proxy.
In this example, I returned target[property] at the end of the get method, which is to allow the read operation to proceed. Since the Proxy get method is called first, the content returned here is the result we can get from the read operation; if we do not return any value here, we will get undefined.
receiver and dead loop
It should be noted that you must not read the receiver's attributes in the get method, because receiver is essentially proxy itself, so this code is equivalent to calling the get method again and causing a dead loop.
const obj = { key: 1 } const proxy = new Proxy(obj, { get: function(target, property, receiver) { () return target[property] } }) () // A vicious cycle!
getter on the prototype chain
Sometimes, we use getters and setters in objects to customize the assignment and reading of properties. At this time, if target[property] is used inside the proxy get method, the value of target[property] will be affected by the getter of the target object. Therefore, when calling the get method, please pay attention to whether getter is used in the target object.
const obj = { get key() { return 'string' }, set key(value) { (`key is ${value}, it is a ${typeof value}`) } } const proxy = new Proxy(obj, { get: function(target, property, receiver) { if(typeof target[property] !== 'string') { return target[property] } else { throw new TypeError(`The type of ${property} is String!`) } } }) = 100 (proxy, obj) // key is 100, it is a number // The type of key is String!
In the example above, if you access the non-numeric property of obj, an error will be thrown, but due to the getter in obj, no matter what value I assign to the key property, an error will definitely be thrown when accessing the key property.
It is easy to just pay attention to getters in the target object, but if the target object inherits from other objects, things will become a bit troublesome. Please see the following example:
const parentObj = { get key() { return 'string' }, set key(value) { (`key is ${value}, it is a ${typeof value}`) } } const obj = (parentObj) const proxy = new Proxy(obj, { get: function (target, property, receiver) { if (typeof target[property] !== 'string') { return target[property] } else { throw new TypeError(`The type of ${property} is String!`) } } }) = 100 () // key is 100, it is a number // The type of key is String!
As shown in the code, the target object obj inherits from parentObj, and the getter method is used in parentObj, so the get method using proxy will still report an error. In actual use, the prototype chain may be very long, and getters may exist in any part of the prototype chain, so please be sure to pay attention when using Proxy's get method.
However, if the key on parentObj is blocked, there will be no error throwing. For example, the key declared when creating obj, the code is as follows:
const parentObj = { get key() { return 'string' }, set key(value) { (`key is ${value}, it is a ${typeof value}`) } } const obj = (parentObj, { key: { value: null, writable: true } }) const proxy = new Proxy(obj, { get: function (target, property, receiver) { if (typeof target[property] !== 'string') { return target[property] } else { throw new TypeError(`The type of ${property} is String!`) } } }) = 100 () // 100
Similarly, we can also use the two methods () and () to achieve the same purpose:
(obj, 'key', { value: null, writable: true }) obj = ({}, obj, { key: null })
But be careful not to use ():
obj = (obj, { key: null })
This way of writing cannot block the key attribute on parentObj, and an error will still be thrown when used.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.