Proxy和Reflect
- 攔截操作
-
get(target,propKey,receiver)
讀取屬性時攔截- 攔截器對不可配置(
configurable:false
)且不可寫(writable:false
)的屬性讀取報錯
- 攔截器對不可配置(
-
set(target,propKey,value,receiver)
設(shè)置屬性時攔截- 攔截器對不可配置(
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)
獲取屬性描述時攔截,在未設(shè)置set攔截器時吱肌,設(shè)置屬性也會進入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)
查看對象是否是不可擴展對象時攔截- 返回值必須和目標(biāo)對象的isExtensible屬性一致
Object.isExtensible(proxy)
-
getPrototypeOf(target)
獲取對象的原型對象時攔截- 不可擴展對象必須返回目標(biāo)對象的原型對象
Object.getPrototypeOf(proxy)
Refelect.getPrototypeOf(proxy)
proxy instanceof Object
proxy.__proto__
Object.prototype.isPrototypeOf(proxy)
-
setPrototypeOf(target,proto)
設(shè)置對象的原型對象時攔截- 不可擴展對象不可改變目標(biāo)對象原型
Object.setPrototypeOf(proxy,proto)
-
apply(target,object,args)
實例作為函數(shù)調(diào)用時攔截proxy(...args)
proxy.call(object,...args)
proxy.apply(object,args)
Reflect.apply(proxy,object,args)
-
construct(target,args荔烧,newTarget)
實例作為構(gòu)造函數(shù)調(diào)用時攔截- newTarget默認是代理后的對象
new proxy(...args)
-
-
Proxy.revocable()
const proxy = Proxy.revocable({},{}) proxy.proxy //代理實例 peoxy.revoke() //取消代理
- 所有攔截操作在Reflect對象上都有對應(yīng)的同名方法來完成默認操作
tips
- get,set攔截方法里的receiver指向當(dāng)前操作所在的對象
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)=>{ /*生成節(jié)點*/ let el = document.createElement(property) /*設(shè)置屬性*/ for(let prop of Object.keys(attrs)){ el.setAttribute(prop,attrs[prop]) } for(child of children){ /*生成子節(jié)點*/ 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方法可以監(jiān)聽到數(shù)據(jù)變更,可以在set方法里執(zhí)行相應(yīng)的處理函數(shù)來實現(xiàn)觀察者模式