Offer to come, dig friends take it! I am participating in the 2022 Spring Recruit Punch card activity. Click here for details.
Ask questions
- What is the difference between Object.defineProperty() and proxy?
- Why do VUE3 choose proxy and what are the benefits?
proxy
Proxy objects are used to create a Proxy for an object to intercept and customize basic operations (such as property lookup, assignment, enumeration, function calls, and so on).
We all know how to use Proxy
const p = new Proxy(target, handler)
Copy the code
Take a look at the internal ECMAScript 2017 (ECMA-262) Proxy
You can see that two parameters are received (target, handler)
- Error if target is undefined
- runProxyCreate(
target
.handler
)
Here is the implementation of ProxyCreate
To exclude error handling, the core code starts at 5 and creates a new empty object p,
Set p object internal methods (except for [[call]] and [[Construct]]) to the definition specified in 9.5,
Then set p’s call and Construct methods,
[[ProxyTarget]] and [[ProxyHandler]]
Return object p
What can we intercept with them?
For most operations on objects, there is a so-called “inner method” in the JavaScript specification that describes how the lowest level of operations work. For example, [[Get]], internal methods for reading properties, [[Set]], internal methods for writing properties, and so on. These methods are only used in the specification and we cannot call them directly by method name.
The Proxy capture intercepts the invocation of these methods. They are listed in the proxy specification and in the following table.
For each internal method, there is a catcher in this table: method names that can be added to the handler parameter of the new Proxy to intercept operations:
For most operations on objects, there is a so-called “inner method” in the JavaScript specification that describes how the lowest level of operations work. For example, [[Get]], internal methods for reading properties, [[Set]], internal methods for writing properties, and so on. These methods are only used in the specification and we cannot call them directly by method name.
The Proxy capture intercepts the invocation of these methods. They are listed in the proxy specification and in the following table.
For each internal method, there is a catcher in this table: method names that can be added to the handler parameter of the new Proxy to intercept operations:
Internal methods | Handler method | When the trigger |
---|---|---|
[[Get]] |
get |
Reads the properties |
[[Set]] |
set |
Write attributes |
[[HasProperty]] |
has |
in The operator |
[[Delete]] |
deleteProperty |
delete The operator |
[[Call]] |
apply |
A function call |
[[Construct]] |
construct |
new The operator |
[[GetPrototypeOf]] |
getPrototypeOf |
Object.getPrototypeOf |
[[SetPrototypeOf]] |
setPrototypeOf |
Object.setPrototypeOf |
[[IsExtensible]] |
isExtensible |
Object.isExtensible |
[[PreventExtensions]] |
preventExtensions |
Object.preventExtensions |
[[DefineOwnProperty]] |
defineProperty |
Object.defineProperty.Object.defineProperties |
[[GetOwnProperty]] |
getOwnPropertyDescriptor |
Object.getOwnPropertyDescriptor.for.. in .Object.keys/values/entries |
[[OwnPropertyKeys]] |
ownKeys |
Object.getOwnPropertyNames.Object.getOwnPropertySymbols.for.. in .Object.keys/values/entries |
Reflect
Reflect is a built-in object that simplifies Proxy creation.
The internal methods mentioned earlier, such as [[Get]] and [[Set]], are normative only and cannot be called directly.
The Reflect object makes it possible to call these internal methods. Its methods are minimal wrappers of internal methods.
In particular, Reflect allows us to change the operators (new, delete…) As a function (reflect.construct, reflect.deleteProperty…) Perform the call. This is an interesting feature, but there is another important point here.
For every availableProxy
Capture internal methods inReflect
Each has a corresponding method whose name and parameters areProxy
Same catcher.
So, we can use Reflect to forward the action to the original object.
We can rewrite the catcher to be shorter:
get(target, prop, receiver) {
return Reflect.get( ... arguments);
}
Copy the code
The Reflect call is named exactly the same as the catcher and takes the same arguments. They are specially designed in this way.
So return Reflect… Provides a secure way to easily forward operations and ensure that we don’t forget anything about it.
Limitations of Proxy
1. Internal slots cannot be proxy
Many built-in objects, such as maps, sets, dates, promises, and so on, use so-called “internal slots.”
Such as:
let map = new Map();
let proxy = new Proxy(map, {});
proxy.set('test', 1); // Error
Copy the code
The solution is to bind the value of get to the target object and then return it
let map = new Map(); let proxy = new Proxy(map, { get(target, prop, receiver) { let value = Reflect.get(... arguments); return typeof value == 'function' ? value.bind(target) : value; }}); proxy.set('test', 1); alert(proxy.get('test')); // 1 (working!)Copy the code
2. Private fields are the same as above
3. peoxy ! = target
This is easy to understand, proxy objects and target objects are not === =
conclusion
A Proxy is a wrapper around an object, forwarding operations on the Proxy to the object, and optionally capturing some of them.
It can wrap any type of object, including classes and functions.
Grammar:
let proxy = new Proxy(target, {
/* trap */
});
Copy the code
… Then, we should use proxy everywhere instead of target. The broker has no properties or methods of its own. If a trap is provided, it captures the operation, otherwise it is forwarded to the target object.
We can capture
- Get, set, deleteProperty, etc
- Function call (Apply catcher)
- New operation (Construct catcher)
Reflect aims to complement Proxy. For any Proxy capture, there is a Reflect call with the same parameters. We should use them to forward the call to the target object.
The limitations of the Proxy
- Unable to proxy internal slots for internal objects
- Unable to proxy private fields
- The proxy object is not equal to the target object
Object.defineProperty
The object.defineProperty () method directly defines a new property on an Object, or modifies an existing property of an Object, and returns the Object.
grammar
Object.defineProperties(obj, props)
Copy the code
describe
There are two main forms of property descriptors that currently exist in objects: data (property) descriptors and access descriptors (accessor properties). A data descriptor is a property with a value that can be writable or unwritable. Access descriptors are properties described by getter and setter functions. A descriptor can only be one of these two; You can’t be both.
Attribute descriptor
- Value – the value
writable
– if fortrue
, the value can be modified, otherwise it is only readable.enumerable
– if fortrue
, will be listed in the loop, otherwise will not be listed.configurable
– if fortrue
, this attribute can be deleted, and these features can be modified. Otherwise, they cannot be.
Accessor properties
- Get — a function with no arguments that works when reading properties,
- Set — a function with one argument, called when the property is set,
- Enumerable — Same as a data attribute,
- Different — the same as the data attribute.
Answer the first question
What is the difference between Object.defineProperty() and proxy?
Object.defineProperty | Proxy |
---|---|
Adds/modifies attributes of an object, defines its description, and returns the object | Proxy target object, intercepts its operation and returns the proxy object |
There are data descriptors and accessor descriptors | Intercept 13 kinds of operations |
Only regular objects can be proxy | Can proxy any object (function, array, class) |
– | Cannot proxy internal slots for internal objects |
Answer the second question
Why do VUE3 choose proxy and what are the benefits?
- Can proxy any object including arrays and functions, objects
- More basic semantic operations (get,set,delete…) than Object.defineProperty()
- Instead of looping through an Object and then using Object.defineProperty(), a Proxy can Proxy all properties within an Object.
- Object.defineproperty () can only hijack attributes of an Object (adding attributes to an Object cannot be detected by vue)