Proxy and Reflect are new apis for manipulating objects in ES6.

Proxy

  • A Proxy is a Proxy for certain operations.
  • Proxy can be understood as assuming an “interception layer” in front of the target object. All external access to the object must pass the interception layer first. Therefore, Proxy also provides a mechanism for filtering and rewriting external access. It can also be understood as “data hijacking”.

Proxy Basic syntax


  • Commonly used: set, get, has, deleteProperty, apply
  • Other: GetPrototypeOf, setPrototypeOf, isExtensible, preventExtensions, getOwnPropertyDescription, defineProperty, ownKeys, the construct

Proxy Basic Application

let test = {
  name: 'zyh',
  boy: {
    name: 'zy',
    age:0
  }
}
var obj = new Proxy(test,{
  get: function(target, key, receiver){
    console.log('getting')
    return Reflect.get(target, key, receiver)
  },
  set: function(target, key, value, receiver){
    console.log('setting')
    return Reflect.set(target, key, value, receiver)
  }
})
obj.count = 1
// setting
Copy the code

The above example can be thought of as the Proxy overload point operator. A function is also an object, so, Proxy can also be a function.

var func = (a, b)=> {
 return a + b
}
var fproxy = new Proxy(func, {
  apply: function (target, ctx, args) {
    console.log('do sth')
    returntarget(... args) } })Copy the code
  • Proxies allow us to control external access to objects in a concise and easy-to-understand way. The functionality is similar to that of the proxy pattern in design mode.
  • Sometimes we can delegate some non-core logic to the Proxy, such as access logging, access control, attribute validation, etc., to achieve separation of concerns.

Form validation Demo

Var isNotEmpty = value => value! = =' ';

  var isNumber = value => /^[0-9]*$/.test(value);

  var isBetween = (value, min, max) => {
    if (max === undefined) {
      max = Number.MAX_VALUE;
    }
    if (min === undefined) {
      min = Number.MIN_VALUE;
    }
    returnvalue > min && value < max; } // Validatorlet validators = {
    name: [{
      validator: isNotEmpty,
      errorMsg: 'Name cannot be empty'
    }],
    age: [
      {
        validator: isNumber,
        errorMsg: 'Age must be a number'
      },
      {
        validator: isBetween,
        errorMsg: 'Age must be greater than 0 and less than 100', params: [0, 100]}]} var validatorCreater = (target, validator) => new Proxy(target, { validator,set(target, key, value, receiver) {// If the assigned attribute has a validator, the validator is performedif(this._validator[key]) {// Traverses its multiple child validatorsfor (validatorStrategy of this._validator[key]) {
        let { validator, errorMsg = ' ', params = [] } = validatorStrategy;
        if(! validator.call(null, value, ... params)) { throw new Error(errorMsg);return false; }}} // The assignment statement is placed last, and does not assign if it fails, or if there is no validatorreturnReflect.set(target, key, value, receiver); }})Copy the code

Complete demo

The Proxy advanced

If a Proxy hijacks an array’s set method, it can detect array changes, which is an improvement over its object.defineProperty ancestor. However, Proxy itself does not support complex objects (the values of objects are also objects), so if you want to hijack the methods of complex objects, That’s going to have to be handled recursively.

const obj = {
    info: {
      name: 'eason',
      blogs: ['webpack'.'babel'.'postcss']}}let handler = {
    get(target, key, receiver) {
      console.log('get', key) // Recursively create and returnif (typeof target[key] === 'object'&& target[key] ! == null) {return new Proxy(target[key], handler)
      }
      return Reflect.get(target, key, receiver)
    },
    set(target, key, value, receiver) {
      console.log('set', key, value)
      return Reflect.set(target, key, value, receiver)
    }
  }
  let proxy = new Proxy(obj, handler)
Copy the code

The obj in the above example is a complex object. For example, when we execute obj.info.name = 2, the console outputs the following:



obj.info
new Proxy()
obj.info.name=2



A complete example

Reflect

In the example above, we already use Reflect. The Reflect object is also intended for a Proxy. Each trap in the Proxy handler has a corresponding Reflect method of the same name. When Reflect is used with a Proxy, the Proxy object can easily invoke the corresponding Reflect method to complete the default behavior, as a basis for modifying the behavior. Here is a brief introduction:

Reflect basic

  • Reflect is a built-in object and, like Proxy, is a new API provided by ES6 for manipulating objects.
  • Reflect is not a function object and has no constructor. Cannot be used with the new operator.
  • All attributes and methods of Reflect are static (like Math objects)

summary

  • Proxy makes it easy for developers to use Proxy mode and clear business logic.
  • Proxy can not only replace Object.defineProperty but also augment a lot of functionality. Proxy technology supports methods such as push monitoring array and dynamic addition and deletion of object attributes, which greatly simplifies the amount of responsive code.