Proxy
在ES6中,新增了一个Proxy类,如果我们希望监听一个对象的相关操作,可以创建一个代理对象,之后对这个对象的所有操作都是通过代理对象来完成,代理对象可以监听想要对原对象的的操作
const per = {
name: "Allen",
age: 18
}
const perProxy = new Proxy(per, {
get(target, key) {
console.log(`the ${key} has been read`, target)
return target[key]
},
set(target, key, newValue) {
console.log(`the ${key} has been set to ${newValue}`, target)
target[key] = newValue
}
})
perProxy.name = "Tony"
perProxy.age = 15
console.log(per.name)
console.log(per.age)
set和get分别对应的是函数类型 set有四个参数:
- target:目标对象
- property:将被设置的属性key
- newValue:新属性值
- receiver:调用的代理对象
get有三个参数:
- target:目标对象
- property:被获取的属性key
- receiver:调用的代理对象
当然proxy还有其他的捕获器
const per = {
name: "Allen",
age: 18
}
const perProxy = new Proxy(per, {
get(target, key) {
console.log(`the ${key} has been read`, target)
return target[key]
},
set(target, key, newValue) {
console.log(`the ${key} has been set to ${newValue}`, target)
target[key] = newValue
},
// 监听in操作的捕获器
has(target, key) {
console.log(`the ${key} has been detected by in`, target)
return key in target
},
// 监听delete操作的捕获器
deleteProperty(target, key) {
console.log(`the ${key} has been deleted`, target)
delete target[key]
}
})
console.log("name" in perProxy)
delete perProxy.name
还有:
handler.getPrototypeOf()—— Object.getPrototypeOf的捕获器handler.setPrototypeOf()—— Object.setPrototypeOf的捕获器handler.isExtensible()—— Object.isExtensible的捕获器handler.preventExtensions()—— Object.preventExtensions的捕获器handler.getOwnPropertyDescriptor()—— Object.getOwnPropertyDescriptor的捕获器handler.defineProperty()—— Object.defineProperty的捕获器handler.apply()—— 函数调用操作的捕获器handler.construct()—— new操作符的捕获器
最后两个是针对函数对象的
function foo() {}
const fooProxy = new Proxy(foo, {
apply(target, thisArg, argArray) {
console.log("foo is called by apply")
return target.apply(thisArg, argArray)
},
construct(target, argArray, newTarget) {
console.log("foo is called by new")
return new target(...argArray)
}
})
fooProxy.apply({}, [123, 456])
new fooProxy(123, 456)
Reflect
Reflect是ES6新增的一个API,是一个对象 像第一段Proxy代码,我们创建proxy就是想要不对原对象进行直接的操作,但是proxy里还是直接操作了,这时可以使用reflect配合proxy一起使用
const per = {
name: "Allen",
age: 18
}
const perProxy = new Proxy(per, {
get(target, key) {
console.log("get-----")
return Reflect.get(target, key)
},
set(target, key, newValue) {
console.log("set-----")
const result = Reflect.set(target, key, newValue)
console.log(result)
}
})
perProxy.name = "Tony"
console.log(perProxy.name)
这样就可以避免直接我们手动操作这个对象了,而是从语言层面去操作这个对象,而且这个Reflect的set方法还会返回一个布尔值,这样还能清晰的看到设置成功与否
Proxy的receiver参数
在Proxy的get/set中有第三个参数receiver,它实际上是我们创建的代理对象
const per = {
_name: "Allen",
get name() {
return this._name
},
set name(newValue) {
this._name = newValue
}
}
const perProxy = new Proxy(per, {
get(target, key, receiver) {
// receiver是创建出来的代理对象
console.log(`${key} has been read`)
return Reflect.get(target, key, receiver)
// 传过去receiver在原对象中get/set访问自身属性时的this会指向receiver,就是获取_name的过程也可以被监听到
},
set(target, key, newValue, receiver) {
console.log(`${key} is set to ${newValue}`)
Reflect.set(target, key, newValue, receiver)
}
})
console.log(perProxy.name)
perProxy.name = "Tony"
主要还是让代理在原对象中调用get/set的时候也能被监听到