代理模式的定義:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用。
Proxy
在ES6中新增了一個(gè)API叫Proxy,Proxy 對(duì)象用于定義基本操作的自定義行為(如屬性查找,賦值,枚舉,函數(shù)調(diào)用等)。
比較抽象,我用一句話總結(jié)就是:Proxy可以覆蓋原有的方法,實(shí)現(xiàn)自定義的默認(rèn)方法的功能。
基礎(chǔ)語(yǔ)法
let p = new Proxy(target, handler);
/**
* target
* 用Proxy包裝的目標(biāo)對(duì)象(可以是任何類型的對(duì)象,包括原生數(shù)組,函數(shù),甚至另一個(gè)代理)
* 一個(gè)對(duì)象,其屬性是當(dāng)執(zhí)行一個(gè)操作時(shí)定義代理的行為的函數(shù)
**/
還是用一段代碼來(lái)演示一下吧
let person = {
name: 'Tom',
age: 18
}
let newP = new Proxy(person, {
get(target, prop) {
if(!(prop in target)) {
return '沒(méi)有對(duì)應(yīng)的屬性'
}
return target[prop]
}
})
console.log(person.name) // Tom
console.log(person.age) // 18
console.log(person.amount) // undefined
console.log(newP.name) // Tom
console.log(newP.age) // 18
console.log(newP.amount) // 沒(méi)有對(duì)應(yīng)的屬性
通過(guò)以上代碼,可以看到當(dāng)訪問(wèn)newP對(duì)象中的屬性時(shí),實(shí)際上是調(diào)用了自定義的get方法,就是說(shuō)我們自定義了一個(gè)get方法覆蓋了原用的get方法。
Proxy的Handler
在Proxy中可以使用到的handler方法如下
handler.getPrototypeOf()
在讀取代理對(duì)象的原型時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.getPrototypeOf(proxy) 時(shí)。
handler.setPrototypeOf()
在設(shè)置代理對(duì)象的原型時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.setPrototypeOf(proxy, null) 時(shí)。
handler.isExtensible()
在判斷一個(gè)代理對(duì)象是否是可擴(kuò)展時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.isExtensible(proxy) 時(shí)。
handler.preventExtensions()
在讓一個(gè)代理對(duì)象不可擴(kuò)展時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.preventExtensions(proxy) 時(shí)。
handler.getOwnPropertyDescriptor()
在獲取代理對(duì)象某個(gè)屬性的屬性描述時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.getOwnPropertyDescriptor(proxy, "foo") 時(shí)。
handler.defineProperty()
在定義代理對(duì)象某個(gè)屬性時(shí)的屬性描述時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.defineProperty(proxy, "foo", {}) 時(shí)。
handler.has()
在判斷代理對(duì)象是否擁有某個(gè)屬性時(shí)觸發(fā)該操作,比如在執(zhí)行 "foo" in proxy 時(shí)。
handler.get()
在讀取代理對(duì)象的某個(gè)屬性時(shí)觸發(fā)該操作,比如在執(zhí)行 proxy.foo 時(shí)。
handler.set()
在給代理對(duì)象的某個(gè)屬性賦值時(shí)觸發(fā)該操作,比如在執(zhí)行 proxy.foo = 1 時(shí)。
handler.deleteProperty()
在刪除代理對(duì)象的某個(gè)屬性時(shí)觸發(fā)該操作,即使用 delete 運(yùn)算符,比如在執(zhí)行 delete proxy.foo 時(shí)。
handler.ownKeys()
Object.getOwnPropertyNames 和Object.getOwnPropertySymbols 的陷阱。
handler.apply()
函數(shù)調(diào)用操作的陷阱。
handler.construct()
new 運(yùn)算符的陷阱。
Proxy的兼容性

image.png
參考
MDN