Take you to play with the proxy object proxy of ES6! ! !

I believe everyone has heard the word proxy!

From the meaning of the word, it means 代理that we will also use this 'word' on some frameworks to configure some scaffolding agents. (Whether it is Vue or React, the proxy can be configured through proxy)

But today we are introducing the Proxy object, a new feature of ES6.

1. Why use Proxy and the concept of Proxy

First, let me talk about its strengths:

  • Use it to modify the underlying behavior of js objects.
  • It provides a way for us to implement some basic object operations ourselves and create a proxy object that is much more advanced than normal objects.
let proxy = new Proxy(target,handlers)
//target 所要拦截的目标对象
//handlers 为处理器对象,用来定制拦截行为。
复制代码

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; //此处执行的时原对象上的set方法。
  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; //此处执行的时代理的set方法。
  console.log(proxy1.a); //11
复制代码

Through the above code, it is not difficult to find that when we configure a proxy for a js object and the proxy object configures some methods, these methods will be overwritten on the target object. When we perform some operations, the proxy object will be executed. methods without executing the methods and properties on the original object. The object's own properties or methods will only be called when the original object is not configured with the property or method proxy.

Note: For this toProxywork, you must operate on theProxyinstance (theproxyobject above), not the target object (the empty object above).

var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"
复制代码

handlerIt is an empty object without any interception effect, and access proxyis equivalent to access target. This also explains the above.

2. Proxy allows us to define a revocable proxy

Revocable proxies are not created with the Proxy constructor, but with the Proxy.revocable() factory function. This function returns an object that contains a proxy object and a revoke() function. Once the revoke() function is called, the proxy is invalidated 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
复制代码

This mechanism is very beneficial for a situation, that is when we use some untrusted third-party libraries. If you have to pass a function to a library that you don't trust, of course, you can't pass your own function directly. We can pass a revocable proxy to it, which can also achieve the same effect. When the library is used, we will Cancel this proxy. security is guaranteed

三、Proxy中this的问题

虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。

const target = {
    m: function () {
      console.log(this === proxy);
    }
  };
  const handler = {};
  
  const proxy = new Proxy(target, handler);
  
  target.m() // false
  proxy.m()  // true
复制代码

四、Proxy支持的拦截操作

  • get(target, propKey, receiver) :拦截对象属性的读取,比如proxy.fooproxy['foo']
  • set(target, propKey, value, receiver) :拦截对象属性的设置,比如proxy.foo = vproxy['foo'] = v,返回一个布尔值。
  • has(target, propKey) :拦截propKey in proxy的操作,返回一个布尔值。
  • deleteProperty(target, propKey) :拦截delete proxy[propKey]的操作,返回一个布尔值。
  • ownKeys(target) :拦截Object.getOwnPropertyNames(proxy)Object.getOwnPropertySymbols(proxy)Object.keys(proxy)for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
  • getOwnPropertyDescriptor(target, propKey) :拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
  • defineProperty(target, propKey, propDesc) :拦截Object.defineProperty(proxy, propKey, propDesc)Object.defineProperties(proxy, propDescs),返回一个布尔值。
  • preventExtensions(target) : intercept Object.preventExtensions(proxy), return a boolean.
  • getPrototypeOf(target) : Intercept Object.getPrototypeOf(proxy), return an object.
  • isExtensible(target) : Intercept Object.isExtensible(proxy), return a boolean.
  • setPrototypeOf(target, proto) : Intercept Object.setPrototypeOf(proxy, proto), return a boolean. If the target object is a function, there are two additional operations that can be intercepted.
  • apply(target, object, args) : Intercept the operation of the Proxy instance as a function call, such as proxy(...args), proxy.call(object, ...args), proxy.apply(...).
  • construct(target, args) : Intercept the operation of the Proxy instance as a constructor call, eg new proxy(...args).

These interception operations will not be discussed one by one, I will only talk about some of my own views. If you want to understand the interception operation, you can go to Mr. Ruan Yifeng's blog: es6.ruanyifeng.com/#docs/proxy


Finally, because Proxy can proxy the entire object, there is no need Object.defineProperty()to recursively traverse every attribute of the object to add get and set to them to achieve the monitoring effect. Vue3 uses Proxy instead of Object.defineProperty() to hijack data, optimize the code, and reduce most of the performance. (The bottom layer of Vue3 is only understood for the time being, and has not been studied in depth!!!)


Finally, I sincerely hope that this article can bring you some help.

周末快乐!

Guess you like

Origin juejin.im/post/7079351796279279647