Proxy 可以理解成在目标对象前架设一个“拦截”层,外界对该对象的访问都必须先通过这层拦截,因此提供了一种机制可以对外界的访问进行过滤和改写
let obj = new Proxy({
}, {
get (target, p, receiver) {
console.log('getter')
return Reflect.get(target, p, receiver)
},
set (target, p, value, receiver) {
console.log('setter')
return Reflect.set(target, p, value, receiver)
},
})
obj.count = 1// setter
console.log(obj.count)// getter 1
同一拦截器函数可以设置拦截多个操作
const handler = {
get (target, name) {
if (name === 'prototype') {
return Object.prototype
}
return `hello ${
name}`
},
apply (target, thisBinding, args) {
return args[0]
},
construct (target, args) {
return {
value: args[1] }
},
}
let fproxy = new Proxy(function (x, y) {
return x + y
}, handler)
console.log(fproxy(1, 2))// 1
console.log(new fproxy(1, 2))// {value: 2}
console.log(fproxy.prototype === Object.prototype)// true
console.log(fproxy.foo)// hello foo
this 问题
在 Proxy 代理的的情况下,目标对象内部的 this 关键字会指向 Proxy 代理
const target = {
test: function() {
console.log(this === proxy)
}
}
const proxy = new Proxy(target, {
})
target.test()// false
proxy.test()// true
然而,有些原生对象的内部属性只有通过正确的 this 才能获取,所以 Proxy 也无法代理这些原生对象的属性
const target = new Date()
const handler = {
}
const proxy = new Proxy(target, handler)
console.log(target.getDate())// 13
console.log(proxy.getDate())// Uncaught TypeError: this is not a Date object.
解决方法:
const target = new Date()
const handler = {
get(target, prop) {
if (prop === 'getDate') {
// 用 this 绑定原始原始对象解决这个问题
return target.getDate.bind(target)
}
return Reflect.get(target, prop)
}
}
const proxy = new Proxy<