(十二) Proxy和Reflect

1. Proxy

1. proxy是什么

MDN给出的定义是: proxy对象用于定义基本操作的自定义行为, 例如属性查找, 赋值, 枚举, 函数调用等

proxy捕获对其目标对象进行的调用和操作, 然后可以更优雅的处理这些调用和操作, 它在目标对象周围创建了一个无法检测的屏障, 将所有操作重定向到处理程序对象

基本用法

代理使用new Proxy()来创建, 该构造函数接受两个必要的参数: 目标对象target处理程序对象handler

let target = {}
let handler = {
  // target操作的处理方法
}
let proxyObject = new Proxy(target, handler)

@理解:

proxy相当于一个黑匣子, 封装对目标对象的处理, proxy的实例对象相当于对外暴露的接口,外部人员对目标对象的操作不再直接作用于目标对象, 而是通过proxy实例对象重定向到proxy内部的处理方法上(像get set等) , 最后再将处理后的最终结果返回给proxy实例

(十二) Proxy和Reflect

2. 常用的代理方法

这些代理方法其实就是proxy对原生方法的监听, 然后用内部对应的方法去处理

2.1 get方法

可以接收三个参数: 目标对象、属性名、[ proxy实例 ]

get方法可以看作是对目标对象操作的代理

let target = { id: 100 }
let handler = {
  get: function (target, prop) {
    if (target.hasOwnProperty(prop)) {
      return target[prop]
    }
  }
}

let proxy = new Proxy(target, handler)
console.log(proxy.id)

2.2 set方法

可以接收四个参数: 目标对象, 属性名, 属性值, [ proxy实例 ]

set方法可以看作是对目标对象某个属性的赋值代理

let target = { id: 100 }
let handler = {
  set: function (target, prop, value) {
    if (value > 500) {
      console.log('超出最大值');
    } else {
      target[prop] = value
    }
  }
}

let proxy = new Proxy(target, handler)
proxy.id = 600   // 超出最大值
proxy.name = '猫13'
proxy.id = 200
console.log(proxy.id)  // 200
console.log(proxy.name)  // 猫13

2.3 deleteProperty方法

接收两个参数: 目标对象, 待删除的属性名

相当于delete obj.prop

let person = {
  usr1: [1, {
    name: '猫13'
  }],
  usr2: [2, {
    name: '猫14'
  }],
}
// 之前删除是这样的
// delete person.name  下面用Proxy来拦截
var handler = {
  deleteProperty(target, key) {
    if (target[key][0] === 1) {
      console.log('usr1不能被删除');
    } else {
      delete target[key]
    }
  }
};
let proxy = new Proxy(person, handler);
delete proxy.usr1		// usr1不能被删除
delete proxy.usr2

console.log(proxy)		// Proxy {usr1: Array(2)}

2.4 apply方法

该方法主要用于拦截函数的调用

接受的第一个参数是目标函数

let t1 = function () {
  console.log('hi');
}

let handler = {
  apply: function (sayHi) {
    console.log(`你的${t1.name}方法被拦截了`)
  }
}

let proxy = new Proxy(target, handler)
proxy()  // 你的t1方法被拦截了

2.5 has方法

has() 方法是针对 in 操作符的代理方法

接收两个参数: 目标对像, 属性名

let target = { iid: 100, uid: 200 }
let handler = {
  has: function (target, prop) {
    if (prop[0] === 'i') {
      return false
    }
    return prop in target
  }
}

let proxy = new Proxy(target, handler)
console.log('iid' in proxy);    // false
console.log('uid' in proxy);    // true

Proxy - 更多方法参考MDN

2. Reflect

个人理解: reflect将proxy代理方法的内部处理做了封装, 简化了操作步骤

另外: proxy有的代理方法, reflect也有

简单看一下

let target = {}
let handler = {
  set: function (target, prop, value) {
    // 之前我们这样赋值
    // target[prop] = value

    // 使用reflect可以这样
    Reflect.set(target, prop, value)
  }
}

let proxy = new Proxy(target, handler)
proxy.name = "猫13"
console.log(proxy.name)   // 猫13
上一篇:golang 反射的基本使用、通过反射获取结构体标签案例


下一篇:Go反射原理