SoFunction
Updated on 2025-02-28

Proxy-Reflect operation method in JavaScript

1. Monitoring object operations

Let's first look at a requirement: there is an object, we want to listen to the process of setting or obtaining properties in this object.

  • Can we achieve this through the knowledge we have learned before?
  • In fact, it is OK. We can do it by storing the attribute descriptor in the previous attribute descriptor; listen to the object's operations

The code on the left uses the previous onesStore attribute descriptorsTo listen for the operation of the attribute.

const obj = {
    name: "why",
    age: 18,
    height: 1.88
}
// Requirements: Listen to all operations of object properties// Listen to attribute operations// 1. For a property// let _name = 
// (obj, "name", {
//   set: function(newValue) {
// ("Listen: Set a new value for name:", newValue)//     _name = newValue
//   },
//   get: function() {
// ("Listen: Get the value of name")//     return _name
//   }
// })
// 2. Listen to all properties: traverse all properties, use defineProperty for each propertyconst keys = (obj)
for (const key of keys) {
    let value = obj[key]
    (obj, key, {
        set: function(newValue) {
            (`monitor: Give${key}Set a new value:`, newValue)
            value = newValue
        },
        get: function() {
            (`monitor: Get${key}Value of`)
            return value
        }
    })
}
// ()
//  = "kobe"
()
 = 17
()

But what are the disadvantages of doing this?

  • First of all, the original intention of design is not to listen to all attributes in an object.
    • When we define certain attributes, our original intention is to define ordinary attributes, but later we forcefully turn them into data attribute descriptors.
  • Secondly, if we want to listen for more abundant operations, such as adding new attributes and deleting attributes, then there is nothing we can do.

So we need to knowStore data descriptorsThe original intention of design is not to monitor a complete object.

2. Basic use of Proxy

In ES6, a new Proxy class was added. This class can be seen from its name and is used to help us create a proxy:

  • That is, if we wishListen to an object's related operations, then we can first create a proxy object (Proxy object);
  • All operations on the object are thenCompleted by proxy object, the proxy object can listen to what operations we want to perform on the original object;

We can implement the above case with Proxy once:

  • First, we need a new Proxy object and pass it inObjects that need to be listened toas well asA processing object, can be calledhandler
    • const p = new Proxy(target, handler)
  • Secondly, our subsequent operations are directly on Proxy operations, rather than the original objects, because we need to listen in the handler;
const obj = {
    name: "why",
    age: 18,
    height: 1.88
}
// 1. Create a Proxy objectconst objProxy = new Proxy(obj, {
    set: function(target, key, newValue) {
        (`monitor: monitor${key}Setting value: `, newValue)
        target[key] = newValue
    },
    get: function(target, key) {
        (`monitor: monitor${key}Get`)
        return target[key]
    }
})
// 2. For all operations of obj, you should operate objProxy// ()
//  = "kobe"
// ()
//  = "james"
 = "Guangzhou City"
()

3. Common Proxy capturers

set and get capturers

If we want to listen for some specific operations, we can add the corresponding one in the handlerCatcher(Trap):

Set and get correspond to function types respectively;

  • The set function has four parameters:
    • target: target object (listening object);
    • property: the property key to be set;
    • value: new attribute value;
    • receiver: the proxy object to be called;
  • The get function has three parameters:
    • target: target object (listening object);
    • property: the acquired property key;
    • receiver: the proxy object to be called;

Other capturers

What do the 13 capturers do?

()

  • Method capture.

()

  • Method capture.

()

  • The method's catcher (judging whether new attributes can be added).

()

  • Method capture.

()

  • Method capture.

()

  • Method capture. Proxy All Captors

()

  • Methods and methods capturers.

()

  • in operator capturer.

()

  • The capturer for the property read operation.

()

  • Properties set the capture of the operation.

()

  • delete operator capture.

()

  • The capturer for function call operations.
  • ()
  • new operator capturer.
const obj = {
    name: "why",
    age: 18,
    height: 1.88
}
// 1. Create a Proxy objectconst objProxy = new Proxy(obj, {
    set: function(target, key, newValue) {
        (`monitor: monitor${key}Setting value: `, newValue)
        target[key] = newValue
    },
    get: function(target, key) {
        (`monitor: monitor${key}Get`)
        return target[key]
    },
    deleteProperty: function(target, key) {
        (`monitor: monitor删除${key}property`)
        delete 
    },
    has: function(target, key) {
        (`monitor: monitorinjudge ${key}property`)
        return key in target
    }
})
delete 
("age" in objProxy)

construct and apply

Of course, we will also see that there are construct and apply in the capture, which are applied to function objects:

function foo(num1, num2) {
    (this, num1, num2)
}
const fooProxy = new Proxy(foo, {
    apply: function(target, thisArg, otherArgs) {
        ("The listener performed the apply operation")
        (thisArg, otherArgs)
    },
    construct: function(target, otherArray) {
        ("The monitor performed new operation")
        (target, otherArray)
        return new target(...otherArray)
    }
})
// ("abc", [111, 222])
new fooProxy("aaa", "bbb")

4. Introduction and function of Reflect

Reflect is also a new API added to ES6, it isAn object, literally meansreflection

So what's the use of this Reflect?

  • It mainly provides many methods for manipulating JavaScript objects, a bit like the methods for manipulating objects in Object;
  • For example (target) is similar to ();
  • For example (target, propertyKey, attributes) is similar to ();

If we have an Object that can do these operations, thenWhat do you need to add new objects like ReflectWoolen cloth?

  • This is because this pair was not considered in the early ECMA specificationsThe object itselfHow to design operations will be more standardized, so put these APIs on Object;
  • butObject as a constructor, these operations are not suitable in fact on it;
  • Including someSimilar to the in, delete operator, making JS look a little strange;
  • So in ES6Added Reflect, let us concentrate these operations on the Reflect object;
  • In addition, when using Proxy, you can do itDon't operate the original object

For the API relationship between Object and Reflect objects, you can refer to the MDN documentation:

/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect/Comparing_Reflect_and_Object_methods

Difference between Object and Reflect: Reflect has a return value

"use strict"
const obj = {
    name: "why",
    age: 18
}
(obj, "name", {
    configurable: false
})
// ()
// 1. Operation in the previous way// delete 
// if () {
// ("name not deleted successfully")// } else {
// ("name deleted successfully")// }
// 
if ((obj, "name")) {
    ("Name deleted successfully")
} else {
    ("The name was not deleted successfully")
}

5. Basic use of Reflect

What are the common methods in Reflect? It corresponds to Proxy one by one, and there are 13:

(target)

  • Similar to ().

(target, prototype)

  • Function that sets the object prototype. Returns a Boolean, and true if the update is successful.

(target)

  • Similar to ()

(target)

  • Similar to (). Returns a Boolean.

(target, propertyKey)

  • Similar to (). If this property exists in the object, the corresponding property descriptor is returned, otherwise undefined.

(target, propertyKey, attributes)

  • Similar to (). Common methods of returning true Reflect if set successfully

(target)

  • Returns an array containing all its own attributes (not including inherited attributes). (similar to (), but not affected by enumerable).

(target, propertyKey)

  • Determining whether an object has a certain property, the function of the in operator is exactly the same.

(target, propertyKey[, receiver])

  • Gets the value of a property on the object, similar to target[name].

(target, propertyKey, value[, receiver])

  • Function that assigns values ​​to attributes. Returns a Boolean, and true if the update is successful.

(target, propertyKey)

  • As the delete operator of the function, it is equivalent to executing delete target[name].

(target, thisArgument, argumentsList)

  • A function can be called, and an array can be passed as a call parameter. Similar to () function.

(target, argumentsList[, newTarget])

  • Performing new operations on the constructor is equivalent to executing new target(…args).

Then we can modify the operations on the original object in the previous Proxy case to Reflect to operate:

const obj = {
    name: "why",
    age: 18
}
const objProxy = new Proxy(obj, {
    set: function(target, key, newValue, receiver) {
        // target[key] = newValue
        // 1. Benefit 1: The purpose of proxying the object: no longer directly operate the original object        // 2. Benefit 2: The method returns the Boolean value, which can determine whether the operation is successful        const isSuccess = (target, key, newValue)
        if (!isSuccess) {
            throw new Error(`set ${key} failure`)
        }
    },
    get: function(target, key, receiver) {
    }
})
// Operation agent object = "kobe"
(obj)

The receiver

We found that when using getters and setters, there is aParameters of receiver, What is its function?

If our source object (obj) has accessor attributes of setter and getter, then the inside can be changed through receiver.this

const obj = {
    _name: "why",
    set name(newValue) {
        ("this:", this) // The default is obj        this._name = newValue
    },
    get name() {
        return this._name
    }
}
//  = "aaaa"
// ()
//  = "kobe"
const objProxy = new Proxy(obj, {
    set: function(target, key, newValue, receiver) {
        // target[key] = newValue
        // 1. Benefit 1: The purpose of proxying the object: no longer directly operate the original object        // 2. Benefit 2: The method returns the Boolean value, which can determine whether the operation is successful        /*
            3. Benefits Three:
              > receiver is the outer Proxy object
              > /get last parameter, which can determine the point of this point of the object accessor setter/getter
         */
        ("The setting method in proxy is called" + key)
        const isSuccess = (target, key, newValue, receiver)
        if (!isSuccess) {
            throw new Error(`set ${key} failure`)
        }
    },
    get: function(target, key, receiver) {
        ("The method in proxy is called")
        return (target, key, receiver)
    }
})
// Operation agent object = "kobe"
()

construct

function Person(name, age) {
     = name
     = age
}
function Student(name, age) {
    // (this, name, age)
    const _this = (Person, [name, age], Student)
    return _this
}
// const stu = new Student("why", 18)
const stu = new Student("why", 18)
(stu)
(stu.__proto__ === )

This is the end of this article about Proxy-Reflect in JavaScript. For more related JavaScript Proxy-Reflect content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!