Open ChuChencheng opened 4 years ago
用于修改某些操作的默认行为,等同于在语言层面做出修改。相当于在目标对象之前架设一层“拦截”,外部对对象的操作,必须通过这层拦截,可对操作进行过滤和改写。
const proxyObject = new Proxy({}, { get (target, key, receiver) { // target: 目标对象 // key: 当前获取的键 // receiver: 当前 Proxy 对象 console.log('getting ', key) return Reflect.get(target, key, receiver) }, set (target, key, value, receiver) { // value 当前设置的值 console.log('setting ', key) return Reflect.set(target, key, value, receiver) }, }) proxyObject.a = 1 // setting a proxyObject.a++ // getting a // setting a // 1
get? (target: T, p: PropertyKey, receiver: any): any
set? (target: T, p: PropertyKey, value: any, receiver: any): boolean
has? (target: T, p: PropertyKey): boolean
propertyKey in proxy
deleteProperty? (target: T, p: PropertyKey): boolean
ownKeys? (target: T): PropertyKey[]
Object.getOwnPropertyNames(proxy)
Object.getOwnPropertySymbols(proxy)
Object.keys(proxy)
for...in
getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor | undefined
Object.getOwnPropertyDescriptor(proxy, propertyKey)
defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean
Object.defineProperty(proxy, propertyKey, propertyDescriptor)
Object.defineProperties(proxy, propertyDescriptors)
preventExtensions? (target: T): boolean
Object.preventExtensions(proxy)
getPrototypeOf? (target: T): object | null
Object.getPrototypeOf(proxy)
setPrototypeOf? (target: T, v: any): boolean
Object.setPrototypeOf(proxy, proto)
isExtensible? (target: T): boolean
Object.isExtensible(proxy)
apply? (target: T, thisArg: any, argArray?: any): any
construct? (target: T, argArray: any, newTarget?: any): object
具体参数说明与用法,可参考各类文档,例如 MDN , typescript 定义,http://es6.ruanyifeng.com/#docs/proxy 等。
定义:
revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; }
返回一个可取消的 Proxy 实例
const { proxy, revoke } = Proxy.revocable({}, {}) proxy.a = 1 proxy.a // 1 revoke() proxy.a // TypeError: Cannot perform 'get' on a proxy that has been revoked
可应用于不允许直接访问对象,必须通过代理访问,访问结束后就收回代理,不能再次访问的场景。
Proxy 中的 this 指向的是 proxy ,而不是原对象,因此,即使 handler 是空的,什么也不拦截,其 proxy 的表现与原对象也不是完全一致的。
const target = { f () { return this } } const proxy = new Proxy(target, {}) target.f() === target // true proxy.f() === target // false proxy.f() === proxy // true
此外,一些原生对象的内部属性,只有通过正确的 this 才能拿到,例如 Date :
Date
const target = new Date() const proxy = new Proxy(target, {}) proxy.getDate() // TypeError: this is not a Date object
如果把 this 绑定回原来的对象,就可以正常使用:
const target = new Date() const proxy = new Proxy(target, { get (target, key) { if (key === 'getDate') { // 判断是否调用的 getDate 方法 return target.getDate.bind(target) } return Reflect.get(target, key) } }) proxy.getDate() // 正常显示日期
http://es6.ruanyifeng.com/#docs/proxy
概念
用于修改某些操作的默认行为,等同于在语言层面做出修改。相当于在目标对象之前架设一层“拦截”,外部对对象的操作,必须通过这层拦截,可对操作进行过滤和改写。
Proxy 的 13 种拦截操作
get? (target: T, p: PropertyKey, receiver: any): any
拦截属性的读取set? (target: T, p: PropertyKey, value: any, receiver: any): boolean
拦截属性的设置has? (target: T, p: PropertyKey): boolean
拦截propertyKey in proxy
操作deleteProperty? (target: T, p: PropertyKey): boolean
拦截删除属性操作ownKeys? (target: T): PropertyKey[]
拦截Object.getOwnPropertyNames(proxy)
,Object.getOwnPropertySymbols(proxy)
,Object.keys(proxy)
,for...in
getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor | undefined
拦截Object.getOwnPropertyDescriptor(proxy, propertyKey)
defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean
拦截Object.defineProperty(proxy, propertyKey, propertyDescriptor)
,Object.defineProperties(proxy, propertyDescriptors)
preventExtensions? (target: T): boolean
拦截Object.preventExtensions(proxy)
getPrototypeOf? (target: T): object | null
拦截Object.getPrototypeOf(proxy)
setPrototypeOf? (target: T, v: any): boolean
拦截Object.setPrototypeOf(proxy, proto)
isExtensible? (target: T): boolean
拦截Object.isExtensible(proxy)
apply? (target: T, thisArg: any, argArray?: any): any
拦截 Proxy 实例作为函数调用的操作construct? (target: T, argArray: any, newTarget?: any): object
拦截 Proxy 实例作为构造函数调用的操作具体参数说明与用法,可参考各类文档,例如 MDN , typescript 定义,http://es6.ruanyifeng.com/#docs/proxy 等。
Proxy.revocable()
定义:
返回一个可取消的 Proxy 实例
可应用于不允许直接访问对象,必须通过代理访问,访问结束后就收回代理,不能再次访问的场景。
this
Proxy 中的 this 指向的是 proxy ,而不是原对象,因此,即使 handler 是空的,什么也不拦截,其 proxy 的表现与原对象也不是完全一致的。
此外,一些原生对象的内部属性,只有通过正确的 this 才能拿到,例如
Date
:如果把 this 绑定回原来的对象,就可以正常使用:
参考
http://es6.ruanyifeng.com/#docs/proxy