Proxy
简单来说,Proxy就是可以用来改变对象的默认操作,比如自定义的set和get行为,常用的有以下这些:
- apply
- construct
- defineProperty
- deleteProperty
- get
- getOwnpropertyDescriptor
- getPrototypeOf
- has
- isExtensible
- ownKeys
- perventExtensions
- set
- setPrototypeOf
Proxy的三个属性 target: 目标对象 handler: 包含重写方法的对象 tarp: 重写的方法,比如get和set
例子
新建一个Proxy对象
let p = new Proxy(target, handler);
新建一个employee对象,然后输出其中的一些属性
const employee = {
firstName: 'fang',
lastName: 'shuqin',
}
console.group('employee')
console.log(employee.firstName)
console.log(employee.lastName)
console.log(employee.org)
// employee
// fang
// shuqin
// undefined
// undefined
使用Proxy更改一些默认行为
- 新建一个使用trap的handler,以下是一个覆盖get方法的handler,当target取不到相应的fileName时,可以自定义输出
let handler = {
get: function(target, filedName){
if(filedName === 'fullName'){
return `${target.firstName} ${target.lastName}`
}
return (filedName in target ) ? target[filedName] : `No such property as, ${filedName}`
}
}
let p = new Proxy(employee, handler)
console.log(p.firstName)
console.log(p.lastName)
console.log(p.fullName)
console.log(p.org)
// fang
// shuqin
// fang shuqin
// No such property as, org
- 再新建一个handler方法,改变原生set方法
const employee = {
firstName: 'fang',
lastName: 'shuqin',
}
let handler = {
set: function(obj,prop, value){
if(prop === 'age') {
if(!Number.isInteger(value)){ //判断是否是整数
throw new TypeError('Age is always an Integer, Please correct it')
}
if(value<0){
throw new TypeError('this is insane, a negative gae ?')
}
}
}
}
let p = new Proxy(employee, handler)
p.age="test"
/*
* Uncaught TypeError: Age is always an Integer, Please correct it
at Object.set (<anonymous>:10:15)
at <anonymous>:20:6
*/
p.age=12
// 12
// //
this的指向
proxy会改变target中的this指向,一旦proxy代理了target,target内部的this则指向了proxy,而不是targer
const target = {
go: function() {
console.log('===this', this===p)
}
}
let p = new Proxy(target, {})
p.go()
// ===this true
- 注意:有些原生对象的内部属性,只有通过正确的this才能拿到,所以proxy无法代理这些原生对象的属性
const target = new Date('2020-4-7')
const p = new Proxy(target, {})
p.getDate()
/*
*VM1470:1 Uncaught TypeError: this is not a Date object.
at Proxy.getDate (<anonymous>)
at <anonymous>:1:3
*/
target.getDate() //月份中的某一天,今天是4.7日
// 7
可以通过this 绑定原始对象来解决这个问题
const target = new Date('2020-4-7')
const handler={
get(target,prop){
if(prop === 'getDate'){
return target.getDate.bind(target)
}
return Reflect.get(target,prop)
}
}
const p = new Proxy(target,handler)
p.getDate()
// 7