Proxy和Reflect
- 拦截操作
-
get(target,propKey,receiver)
读取属性时拦截- 拦截器对不可配置(
configurable:false
)且不可写(writable:false
)的属性读取报错
- 拦截器对不可配置(
-
set(target,propKey,value,receiver)
设置属性时拦截- 拦截器对不可配置(
configurable:false
)且不可写(writable:false
)属性的修改操作无效
- 拦截器对不可配置(
-
has(target,propKey)
in操作时拦截- 拦截器对不可配置(
configurable:false
)的属性或者禁止扩展的对象in操作返回"如果有但是改写成false"报错 propKey in proxy
- 拦截器对不可配置(
-
deleteProperty(target,propKey)
delete操作时拦截- 不可配置(
configurable:false
)属性删除时报错 delete proxy[propKey]
- 不可配置(
-
ownKeys(target)
遍历操作时拦截- 不可配置的属性必须被返回,否则报错
- 不可扩展对象只能返回所有原有配置属性
Object.getOwnPropertyNames(proxy)
Object.getOwnPropertySymbols(proxy)
Object.keys(proxy)
for (let key in proxy)
Reflect.ownKeys(proxy)
-
getOwnPropertyDescriptor(target,propKey)
获取属性描述时拦截,在未设置set拦截器时,设置属性也会进入getOwnPropertyDescriptor
拦截Object.getOwnPropertyDesctiptor(proxy,propKey)
Object.getOwnPropertyDescriptors(proxy)
-
defineProperty(target,propKey,propDesc)
定义属性时拦截- 不可修改不可写或者不可配置的属性
- 不可为不可扩展对象增加属性
Object.defineProperty(proxy,propKey,propDesc)
Object.defineProperties(proxy,propDescs)
-
preventExtensions(target)
使对象变成不可扩展时拦截Object.preventExtensions(proxy)
-
isExtensible(target)
查看对象是否是不可扩展对象时拦截- 返回值必须和目标对象的isExtensible属性一致
Object.isExtensible(proxy)
-
getPrototypeOf(target)
获取对象的原型对象时拦截- 不可扩展对象必须返回目标对象的原型对象
Object.getPrototypeOf(proxy)
Refelect.getPrototypeOf(proxy)
proxy instanceof Object
proxy.__proto__
Object.prototype.isPrototypeOf(proxy)
-
setPrototypeOf(target,proto)
设置对象的原型对象时拦截- 不可扩展对象不可改变目标对象原型
Object.setPrototypeOf(proxy,proto)
-
apply(target,object,args)
实例作为函数调用时拦截proxy(...args)
proxy.call(object,...args)
proxy.apply(object,args)
Reflect.apply(proxy,object,args)
-
construct(target,args,newTarget)
实例作为构造函数调用时拦截- newTarget默认是代理后的对象
new proxy(...args)
-
-
Proxy.revocable()
const proxy = Proxy.revocable({},{}) proxy.proxy //代理实例 peoxy.revoke() //取消代理
- 所有拦截操作在Reflect对象上都有对应的同名方法来完成默认操作
tips
- get,set拦截方法里的receiver指向当前操作所在的对象
const proxy = new Proxy({},{ get(target,propKey,receiver){ return receiver } }) let obj = Object.create(proxy) proxy.a === proxy // true obj.a === obj // true
- get生成dom
const dom = new Proxy({},{ get(target,property){ return (attrs={},...children)=>{ /*生成节点*/ let el = document.createElement(property) /*设置属性*/ for(let prop of Object.keys(attrs)){ el.setAttribute(prop,attrs[prop]) } for(child of children){ /*生成子节点*/ if(typeof child === 'string'){ child = document.createTextNode(child) } el.appendChild(child) } return el } } }) const el = dom.div({}, 'Hello, my name is ', dom.a({href: '//example.com'}, 'Mark'), '. I like:', dom.ul({}, dom.li({}, 'The web'), dom.li({}, 'Food'), dom.li({}, '…actually that\'s it') ) ); document.body.appendChild(el);
- 通过Proxy的set方法可以监听到数据变更,可以在set方法里执行相应的处理函数来实现观察者模式
网友评论