Proxy 和 Reflect

大约 2 分钟

Proxy 和 Reflect

Proxy

Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义,如属性查找、赋值、枚举、函数调用等。

有如下两个参数:

  1. target:要使用Proxy进行代理的对象,可以是数组、函数等甚至是另一个Proxy代理。

  2. handler:一个对象,它的属性一般都是函数,如下:

    • set(target, key, value, receiver) {}:拦截赋值操作

      let person = {
      	name: "zhangsan",
      	age: 18,
      }
      
      person = new Proxy(person, {
      	/**
      	 * @description: 拦截赋值操作
      	 * @param {*} target 代理的对象
      	 * @param {*} key 进行赋值的属性的 key
      	 * @param {*} value 要赋值的新值
      	 * @param {*} receiver 代理的对象,这个属性是为了保证上下文正确
      	 * @return {boolean}
      	 */
      	set(target, key, value, receiver) {
      		console.log(target) // { name: 'zhangsan', age: 18 }
      		console.log(key) // name
      		console.log(value) // lisi
      		console.log(receiver) // { name: 'zhangsan', age: 18 }
      		const result = Reflect.set(target, key, value, receiver)
      		return result
      	},
      })
      
      person.name = "lisi"
      console.log(person) // { name: 'lisi', age: 18 }
      
    • get(target, key, receiver) {}:拦截取值操作

    • apply() {}:拦截函数调用

    • has() {}:拦截 inopen in new window 操作符

    • ownKeys() {}:拦截for...in

    • construct() {}:拦截 new 操作符

    • deleteProperty() {}:拦截delete操作符

    • Proxy | handler 完整方法open in new window

Reflect

Reflect是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与Proxy handler的方法相同。Reflect不是一个函数对象,因此它是不可构造的(不可new)。

在上面一节Proxy handler.set()中,我们可以发现Reflect.set()返回了一个布尔值,并且也给person.name赋值成功,这是因为通过targetreceiver进行定位后,我们可以保证赋值的对象和属性是正确的。

所以,当我们使用Proxy拦截一个对象时,就可以搭配使用Reflect去进行赋值(Reflcet.set())或取值(Reflect.get())。

可能你会觉得,我都有了target & key & value了,就不能直接赋值吗?当然,我们可以试试,如下:

let person = {
	name: "zhangsan",
	age: 18,
}

person = new Proxy(person, {
	set(target, key, value, receiver) {
		// const result = Reflect.set(target, key, value, receiver)
		target[key] = receiver[key] = value // 报错
		return true
	},
})

person.name = "lisi"
console.log(person)
上次编辑于: