preface

Proxy objects are apis for manipulating objects in ES6(ECMAScript 6). Proxy objects are used to define custom behaviors for basic operations (such as attribute lookup, assignment, enumeration, function call, etc.).

  • Small white: forehead ~, read three times, still not quite understand.
  • Lao Wang next door:ProxyWas meant toThe agent, since the agent, must have the two basic qualities of the agent, 1. Who to help the agent, 2. Do something. So, representing who?Help target object proxyDo what?Set up interception, filtering and rewriting access to the outside worldWhen you put it together, you can say:A layer of "interception" is placed in front of the target object, through which all external access to the object must pass, thus providing a mechanism for filtering and rewriting external access. There you go, heh heh.
  • Small white: oh yu, not kui is next door old wang, be fierce ~

grammar

let proxy = new Proxy(target, handler);
Copy the code

Tgarget: Target object to proxy. This can be any type of object, including a native array, a function, or even another proxy. Handler: Configuration object that defines interception behavior (also an object whose internal properties are functions that perform operations).

  • Proxy supports 13 kinds of interception operations, that is, 13 kinds of proxy behavior (function). If you need to copy the behavior of these functions, you need to define the use of the handler object. Here we will illustrate the common operation functions supported by these. The rest are not very commonly used, if you want to know you can refer to the material at the end of the article to learn.

get(target, key, receiver)

Intercepts reading of object attributes Target: the target object to be propped. Key: indicates the attribute name. Receiver: Proxy instance (optional)

const proxy1 = new Proxy({
            a: 1
        }, {
            get(target, key) {
              if(Reflect.has(target,key)) {
                return Reflect.get(target,key);
              }else {
                  return false;
              }
              
            }
    })
        proxy1.a //1
        proxy1.b //false
Copy the code

If the get method is not defined, then the fetch operation will be forwarded to the target object. By default, if there is no get method, undefined is returned. False is returned. Because of the redefinition of the GET method, the returned content is modified, as it is meant to be, to intercept the reading of proxy object properties.

set(target, key, value, receiver)

Interception object attribute setting target: the target object to be proxied. Key: Name of the property to be set. Value: Indicates the value of the property to be set. Receiver: Proxy instance (optional)

    const handler = {
           set(target,key,value) {
               if(! Reflect.has(target,key)) { Reflect.set(target,key,value); }else {
                  console.log(`${key}Property already exists') //a property already exists}}, get(target,key) {returnReflect.get(target,key); } } const proxy = new Proxy({},handler); proxy.a = 1; console.log(proxy.a); //1 proxy.a = 2; console.log(proxy.a) //1Copy the code

If the current attribute already exists, it cannot be set successfully. Therefore, we can use the set method to intercept and set the desired attribute, according to the application scenario, free play.

   var obj = {};
   const target = Object.defineProperty(obj, 'a', {
            value: 123,
            writable: false}); const handler = {set(target,key,value) {
            Reflect.set(target,key,value);
        },
        get(target, key) {
            returnReflect.get(target,key); }}; const proxy = new Proxy(target, handler); proxy.a = 456; console.log( proxy.a) //123Copy the code

Above, the set method is invalidated when an attribute of the target object is not writable.

  • See a lot of data written when the target object’s property isNot writable and not configurableState, the set method will fail, but self-test finds its results withconfigurableThe state of the property does not matterwritableAttribute related, a little doubt, hope to see the big guy can help younger brother to solve doubts.

has(target, Key)

Meaning: Determines whether an object has a property. Target: Indicates the target object to be proxied. Key: Name of the property to be set. The HAS method takes effect when determining whether an object has an attribute. Typically, the in operator is applied and returns a Boolean value

     const handler = {
            has(target, key) {
                if (key[0] === '_') {
                    console.log('it is a private property')
                    return false;
                }
                return key intarget; }}; const target = { _a: 123, a: 456 }; const proxy = new Proxy(target, handler); console.log('_a' in proxy) // it is a private property  false
        console.log('a' inproxy); //true
Copy the code

Above, when the in operator is used for proxy, the has method will be automatically triggered. If it is judged that the current attribute starts with _, it will be intercepted, so as not to be detected by the following IN operator, realizing the purpose of hiding some specific attributes.

Note, however, that the HAS method cannot hide the current properties of the target object when the target object is not extensible or the object’s properties are not configurable, otherwise interception will report an error.

var obj = { a: 10 }; Object.preventExtensions(obj); Var p = new Proxy(obj, {has:function (target, key) {
                return false; }});'a' in p // Uncaught TypeError: 'has' on proxy: trap returned falsish for property 'a' but the proxy target is not extensible
        
        

   let obj = {};
        Object.defineProperty(obj, "a", {
            configurable: false, // The current attribute is not configurable value: 10,}); var p = new Proxy(obj, { has:function (target, key) {
                return false; }});'a' in p // Uncaught TypeError: 'has' on proxy: trap returned falsish for property 'a' which exists in the proxy target as non-configurable
    
Copy the code

apply(target, thisArgs, args)

Intercepts function calls, calls, and apply operations target: the target object. ThisArgs: The context object (this) of the target object. Args: An array of parameters for the target object.

    const handler = {
            apply(target, ctx, args) {
                returnReflect.apply(... arguments) * 2; / / orreturntarget(... args) * 2 } };functionsum(... args) {let num = 0;
            args.forEach((item) => {
                num += item;
            })
            return num;
        }

        var proxy = new Proxy(sum, handler);
        proxy(1, 2) // 6
        proxy.call(null, 5, 6) // 22
        proxy.apply(null, [7, 8]) // 30
Copy the code

Above, the target object, in this case sum, must be a function, otherwise the call will report an error. Whenever the proxy function is called directly or when the call is called, the apply call immediately triggers the Apply method, which is then intercepted by the Apply method so that the interception can be used to modify the return value. If the Apply method is not written, the sum method is called by default and returns the result.

The construct (target, args, newTarget)

Intercepts the new command target: indicates the target object. Args: List of arguments to the constructor. NewTarget: the constructor used by the new command when creating the instance object (p in the following example).

    var p = new Proxy(function () {}, {
            construct: function (target, args, newTarget) {
                console.log('called: ' + args.join(', '));
                return {
                    value: args[0] * 10
                };

               // return 1 //Uncaught TypeError: 'construct' on proxy: trap returned non-object ('1')}}); (new p(1)).value //"called: 1"/ / 10Copy the code

The target object of the proxy must be a constructor (only constructors can use the new operator). When new p(1) is executed, construct is immediately triggered. The construct method completes, and the p instance is initialized.

The “this” reference inside the target is changed during Proxy

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

Copy the code

As you can see, once the target object is proxied by the proxy, its internal this will point to the proxy instead of itself, so you need to pay attention to this.

conclusion

Ok, today’s introduction to Proxy is over here, the above is just for a few more commonly used operation functions for example, if you want to know more, it is recommended to refer to the following information, if there is a mistake, but also hope you are correct!

Nguyen other: introductory ECMAScript 6 – Proxy nguyen one: introductory ECMAScript 6 – Reflect the Proxy – JavaScript | MDN