Recently, I used Proxy in the project and recorded some problems encountered

The Proxy profile

In simple terms, Proxy is to set up an interception on the object, directly on the code

let obj = {
    attr: 1
};
// Intercept obj
obj = new Proxy(obj, {
  get: function (target, key, receiver) {
    // if obj has this property, it returns it directly
    if(key in target) {
        return target[key];
    } 
    // If obj does not have this property, it returns' no such value '.
    return 'There is no such value';
  },
  set: function (target, key, value, receiver) {
    // If you want to set object properties, return (do not set)
    return true; }});/ / use
console.log(obj.attr); / / output 1
console.log(obj.abc); // Print 'no such value ',

obj.attr = 2;//
console.log(obj.attr); // Output 1, object properties cannot be set

Copy the code

There are more types of interception than get and set, for example: (from Teacher Ruan Yifeng’s book ES6 Proxy) :

  • Set (target, propKey, value, receiver) : Intercepts the setting of object properties, such as proxy.foo = v or proxy[‘foo’] = v, and returns a Boolean value.
  • Has (target, propKey) : Intercepts the propKey in proxy operation and returns a Boolean value.
  • DeleteProperty (target, propKey) : Intercepts the operation of delete Proxy [propKey] and returns a Boolean value.
  • OwnKeys (target) : interception Object. GetOwnPropertyNames (proxy), Object. GetOwnPropertySymbols (proxy), the Object. The keys (proxy), for… The in loop returns an array. This method returns the property names of all of the target Object’s own properties, whereas object.keys () returns only the traversable properties of the target Object itself.
  • GetOwnPropertyDescriptor (target, propKey) : interception Object. GetOwnPropertyDescriptor (proxy, propKey), returns the attributes describe objects.
  • DefineProperty (target, propKey propDesc) : Intercepts Object.defineProperty(proxy, propKey, propDesc), Object.defineProperties(proxy, propDescs), and returns a Boolean value.
  • PreventExtensions (target) : Intercepts Object.preventExtensions(proxy), returns a Boolean.
  • GetPrototypeOf (target) : Intercepts object.getProtoTypeof (proxy) and returns an Object.
  • IsExtensible (Target) : Intercepts Object. IsExtensible (proxy), returning a Boolean value.
  • SetPrototypeOf (target, proto) : Intercepts Object.setPrototypeOf(proxy, proto) and 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 as Proxy (… The args), proxy. Call (object,… The args), proxy. Apply (…). . Construct (target, args) : intercepts operations called by Proxy instances as constructors, such as new Proxy (… The args).

These are introduced above are a direct copy of Ruan Yifeng teacher’s book ES6 Proxy

Problems encountered

Intercept the native browser HTMLElement object

1, the interception of this point to the problem is also mentioned in Teacher Ruan’s book

In the intercepting method, this refers to the Proxy object, so when calling the method of the original object, be careful to look directly at the code

let div = document.querySelector('div'); // Take a random page div and delegate it

// First proxy method
let divProxy = new Proxy(div, {
  get: function (target, key, receiver) {
    // Access any attributes of the div, and return them directly
    returntarget[key]; }});// Call div's querySelector method and get the a tag below it
console.log(divProxy.querySelector('a')); // Chrome will display an error: Uncaught TypeError: Illegal Invocation

Copy the code

In the code above, an error is reported because the querySelector method has an access to this. This problem can be fixed by changing to the following code:

let div = document.querySelector('div'); // Take a random page div and delegate it

// The second proxy method
let divProxy = new Proxy(div, {
  get: function (target, key, receiver) {
    if(!!!!! target[key] && !! target[key].bind) {// Use bind to bind this to
        return target[key].bind(target);
    } else {
        returntarget[key]; }}});console.log(divProxy.querySelector('a')); // 

Copy the code

There’s another problem, there’s also a problem with setting the properties of objects by proxy and again, look at the code

let div = document.querySelector('div');
let divProxy = new Proxy(div, {});
// Set the innerHTML attribute of a div. By default, setting an object attribute calls the div.innerhtml.__defineSetter__ method
divProxy.innerHTML = '; // Chrome error: Uncaught TypeError: Illegal Invocation

Copy the code

Go straight to the solution

let div = document.querySelector('div'); 
let divProxy = new Proxy(div, {
    // Block all set actions
    set: function (target, key, value, receiver) {
        if(key in target) {
            target[key] = value; // Call the original object property directly to set (target[key])
        }
        return true; }}); divProxy.innerHTML =';
Copy the code

At the end

Generally, Proxy will be used with Reflect. This article will not introduce it, but will directly go to Ruan’s book.

The syntax of JavaScript is becoming more and more standardized, and the new standard specifications are beginning to fill in the holes. With the widespread use of Babel, we can embrace new syntax, features, and clean code and enjoy ourselves.