Proxy & Reflect
Proxy
首先看下 MDN 对 Proxy 的描述:
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
语法:
js
const p = new Proxy(target, handler)
p
: 代理对象target
: 被包装的目标对象handler
: 拦截操作的处理对象。当触发拦截操作时,执行对应拦截的处理方法
Reflect
首先看下 MDN 对 Reflect 的描述:
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。
最重要的一点,Reflect
提供的静态方法和 Proxy 的 handler
拦截对象方法名一一对应,后面会看到。
拦截 get / set 操作
handler.get()
和 handler.set()
分别用于拦截 get 和 set 操作
js
const obj = { foo: 'bar' }
const p = new Proxy(obj, {
get(target, prop) {
console.log(`拦截 get 操作 '${prop}'`)
return Reflect.get(target, prop)
},
set(target, prop, value) {
console.log(`拦截 set 操作 '${prop}'`)
return Reflect.set(target, prop)
},
})
p.foo
p.foo = 'baz'
拦截枚举操作
handler.ownKeys()
用于拦截:
- Object.keys()
- for ... in
...
扩展符
举几个栗子🌰🌰🌰
- 拦截对象的枚举操作
js
const obj = { foo: 'bar', baz: 'bar' }
const p = new Proxy(obj, {
ownKeys(target) {
console.log('拦截枚举操作', target)
return Reflect.ownKeys(target)
}
})
for (let key in p) {
console.log(key)
}
- 拦截数组的枚举操作
js
const obj = [1, 2]
const p = new Proxy(obj, {
ownKeys(target) {
console.log('拦截枚举操作', target)
return Reflect.ownKeys(target)
}
})
for (let key in p) {
console.log(key)
}
- 拦截 Object.keys()
js
const obj = { foo: 'bar' }
const p = new Proxy(obj, {
ownKeys(target) {
console.log('拦截 Object.keys() 操作', target)
return Reflect.ownKeys(target)
}
})
Object.keys(p)
// or
// for (let key in Object.keys(p)) {
// console.log(key)
// }
- 拦截
...
扩展符
js
const obj = { foo: 'bar' }
const p = new Proxy(obj, {
ownKeys(target) {
console.log('拦截 ... 操作符', target)
return Reflect.ownKeys(target)
}
})
const o = { ...p }
拦截 in
操作符
handler.has()
用于拦截 in
操作符
js
const obj = { foo: 'bar' }
const p = new Proxy(obj, {
has(target, prop) {
console.log('拦截 in 操作符', target)
return Reflect.has(target, prop)
}
})
'foo' in p
拦截 delete 操作
handler.deleteProperty()
用于拦截对象属性的 delete
操作
js
const obj = { foo: 'bar' }
const p = new Proxy(obj, {
deleteProperty(target, prop) {
console.log('拦截 delete 操作', target)
return Reflect.deleteProperty(target, prop)
}
})
delete p.foo
拦截函数调用
handler.apply()
可以拦截函数调用
js
const sum = (a, b) => a + b
const p = new Proxy(sum, {
apply(target, thisArg, argumentsList) {
console.log('拦截函数调用', argumentsList)
return Reflect.apply(target, thisArg, argumentsList)
}
})
console.log(p(1, 2))