I’m sure you’ve all heard of proxy!

The word “proxy” means agent, and we will also use this word on some frames to configure scaffolding agents. (Whether it is Vue or React, you can configure the proxy by proxy.)

But today we are going to introduce a new ES6 feature called Proxy.

First, why use Proxy and the concept of Proxy

Let me start by saying how powerful it is:

  • You can use it to modify the underlying behavior of js objects.
  • It provides a way to implement some basic operations on objects ourselves and create a proxy object that is much more advanced than normal objects.
let proxy = new Proxy(target,handlers)
//target Specifies the target object to intercept
Handlers are the handler objects used to customize interception behavior.
Copy the code

A proxy object creates an object that has no state or behavior of its own.

  var proxy = new Proxy({time: 10 },
    {
      get: function (target, propKey, receiver) {
        console.log(target, propKey, receiver);
        return 999; }});console.log(proxy.time);/ / 999
  proxy.time = 11; // The set method is executed on the original object.
  proxy.time;

  console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
  
  var proxy1 = new Proxy({time: 10 },
    {
      set: function (target, propKey, receiver) {
        target[propKey] = receiver;
        console.log(target, propKey, receiver); }});console.log(proxy1.time); / / 10
  proxy1.a = 11; // The set method of the proxy is executed here.
  console.log(proxy1.a); / / 11
Copy the code

As you can see from the above code, when we configure the proxy for a JS object and the proxy object configures some methods, these methods will overwrite the target object, and when we do some operations, we will execute the proxy object’s methods, but not the original object’s methods and properties. The object’s own property or method is called only if no proxy on the property or method has been configured for the original object.

Note: For Proxy to work, you must operate on the Proxy instance (the Proxy object in this example), not the target object (the empty object in this example).

var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"
Copy the code

Handler is an empty object with no interception effect, and accessing the proxy is the same as accessing target. That would also explain the above.

Proxy allows us to define an undoable Proxy

Instead of using the Proxy constructor, a revocable Proxy is created using the proxy.revocable () factory function. This function returns an object that contains a revoke object and a REVOKE () function. The revoke() function revokes the revoke immediately.

  function func() {
    return 111;
  }

  let { proxy, revoke } = Proxy.revocable(func, {});
  console.log(proxy()); / / 111
  revoke();
  console.log(proxy()); //Uncaught TypeError: Cannot perform 'apply' on a proxy that has been revoked
Copy the code

This mechanism is particularly useful in situations where we are using untrusted third-party libraries. If we have to pass a function to a library that we don’t trust, we can pass it a proxy that can be undone. This will also work. When we are done with the library, we will revoke the proxy. To ensure safety

3. This problem in Proxy

Although Proxy can Proxy the access of the target object, it is not a transparent Proxy of the target object, that is, without any interception, it cannot guarantee the consistency with the behavior of the target object. The main reason is that in the case of Proxy, the this keyword inside the target object points to Proxy.

const target = {
    m: function () {
      console.log(this=== proxy); }};const handler = {};
  
  const proxy = new Proxy(target, handler);
  
  target.m() // false
  proxy.m()  // true
Copy the code

4. Interception operations supported by Proxy

  • get(target, propKey, receiver): intercepts the reading of object properties, such asproxy.fooandproxy['foo'].
  • set(target, propKey, value, receiver): Intercepts the setting of object properties, such asproxy.foo = vorproxy['foo'] = v, returns a Boolean value.
  • has(target, propKey)Intercept:propKey in proxyReturns a Boolean value.
  • deleteProperty(target, propKey)Intercept:delete proxy[propKey]Returns a Boolean value.
  • ownKeys(target)Intercept:Object.getOwnPropertyNames(proxy),Object.getOwnPropertySymbols(proxy),Object.keys(proxy),for... inLoop to return an array. This method returns the property names of all of the target object’s own properties, andObject.keys()The return result of the object contains only the traversable properties of the target object itself.
  • getOwnPropertyDescriptor(target, propKey)Intercept:Object.getOwnPropertyDescriptor(proxy, propKey)Returns the description object of the property.
  • defineProperty(target, propKey, propDesc)Intercept:Object. DefineProperty (proxy, propKey propDesc),Object.defineProperties(proxy, propDescs), returns a Boolean value.
  • preventExtensions(target)Intercept:Object.preventExtensions(proxy), returns a Boolean value.
  • getPrototypeOf(target)Intercept:Object.getPrototypeOf(proxy), returns an object.
  • isExtensible(target)Intercept:Object.isExtensible(proxy), returns a Boolean value.
  • setPrototypeOf(target, proto)Intercept:Object.setPrototypeOf(proxy, proto), returns a Boolean value. If the target object is a function, there are two additional operations that can be intercepted.
  • apply(target, object, args): Intercepts operations called by Proxy instances as functions, such asproxy(... args),proxy.call(object, ... args),proxy.apply(...).
  • construct(target, args): intercepts operations called by Proxy instances as constructors, such asnew proxy(... args).

I won’t go into all of these interceptions, but I’ll just give you my own opinion. If you want to know about interception, you can go to see Teacher Ruan Yifeng’s blog: es6.ruanyifeng.com/#docs/proxy


Finally, because a Proxy can Proxy an entire Object, you don’t need to recursively traverse every attribute of an Object like object.defineProperty () to add a GET or set to it to listen. Vue3 uses proxies instead of Object.defineProperty() for data hijacking, optimizing the code and reducing most of the performance. (Vue3 is a basic part of the temporary understanding, not in-depth study!!)


Have a great weekend!