前端項目反向代理原理?// pOjb就是通過new Proxy創建的代理對象
var pObj = new Proxy(obj, handlers)
,今天小編就來說說關于前端項目反向代理原理?下面更多詳細答案一起來看看吧!
前端項目反向代理原理
// pOjb就是通過new Proxy創建的代理對象
var pObj = new Proxy(obj, handlers)
舉個記賬的例子:
// obj代表我們,wallet屬性指我們錢包,現在我們錢包裡有100元
// consume指消費次數,每次消費加1, 記一筆賬
var obj = {wallet: 100}
var consume = 0
// 這個月,我們喝了五次肥宅快樂水,每次消費我們都記一筆
// 今天消費3元
consume
obj.wallet = 97
// 今天消費3元
consume
obj.wallet = 94
// 今天消費3元
consume
obj.wallet = 91
// 今天消費3元
consume
obj.wallet = 88
// 今天消費3元
consume
obj.wallet = 85
每次我們修改錢包剩餘金額時,都要執行一次consume 去執行一次記賬的操作。有沒有更簡單的方式,不需要每次都寫上一行代碼去增加消費次數呢?
答案當然有,它就是Proxy代理對象!使用代理對象,你想對目标對象的屬性操作全部改為對代理對象相同屬性的操作,代理對象提供了對屬性獲取 [[get]] 修改 [[set]] 等操作的攔截,js将這種攔截稱為trap(捕捉器)。
通過捕捉器,我們就可以捕獲到 代碼中對屬性的操作時機,讓我們能夠先執行我們自定義的業務邏輯代碼。因為我們對目标對象的屬性操作改為了對代理對象相同的屬性操作,所以我們在最後需要通過Reflact執行目标對象的原始操作。
var consume = 0
// 目标對象
var obj = {wallet: 100}
// 捕獲器trap
var handlers = {
set(target, key, val) {
// target 目标對象
// key 代理對象要修改的屬性
// 記錄一筆消費
consume
// 通過Reflact對象觸發原始目标對象的屬性操作
// 相當于執行 target[key] = val
Reflect.set(target, key, val)
}
}
// 代理對象
var pObj = new Proxy(obj, handlers)
// 将對目标對象obj的屬性wallet操作改為代理對象相同屬性wallet的操作
pObj.wallet = 97
pObj.wallet = 94
pObj.wallet = 91
pObj.wallet = 88
pObj.wallet = 85
console.log(obj.wallet) // 85
console.log(consume) // 5
假如某一天,你實現了财務自由,不需要再精打細算記錄每一筆消費了,你可能就需要取消此前的代理,代碼很簡單,往下看:
var consume = 0
var obj = {wallet: 100}
var handlers = {
set(target, key, val) {
consume
Reflect.set(target, key, val)
}
}
// 使用Proxy.revocable創建代理
var tmpObj = Proxy.revocable(obj, handlers)
var pObj = tmpObj.proxy
var prevoke = tmpObj.revoke
// 使用代理對象進行消費記賬
pObj.wallet = 97
pObj.wallet = 94
pObj.wallet = 91
// 某一天,我們實現了一個小目标
pObj.wallet = 100000000
// 我們不需要記賬了,我們需要取消創建的代理
prevoke() // 執行prevoke即可,就是這麼簡單 哦耶~
pObj.wallet = 99999997 // TypeError 報錯啦 (代理取消之後就不能使用了喲!)
前面的示例都是先執行代理捕獲器中的業務邏輯,最後再通過Reflect執行目标對象的屬性操作,這種捕獲代碼操作在前,目标對象操作在後的模式稱為“代理在先”模式,有在先,當然就有在後模式。
當然這裡的“代理在後”模式并不是先使用Reflect對象觸發目标對象屬性操作,在執行捕獲器中的其他操作代碼。而是指代理作為目标對象的一種補充,我們仍然操作的是目标對象,隻是當某些操作在目标對象上無法實現時,才使用代理對象。
等會,當某些操作目标對象無法提供時,js會向目标對象的原型prototype上進行查找,所以“代理在後”模式是對目标對象的原型進行代理!
var handlers = {
get(target, key, context) {
return function () {
context.speak(key '!')
}
}
}
var catchall = new Proxy({}, handlers)
var greeter = {
speak(who = 'someone') {
console.log('hello ', who)
}
}
// 将catchall設置為greeter的原型
Object.setPrototypeOf(greeter, catchall)
greeter.speak() // hello someone
greeter.speak('world') // hello world
// 執行greater上不存在的方法
greeter.everyone() // hello everyone!
Reflect對象用來觸發目标對象執行相應的操作,就是這麼簡單!
Reflect.get(target, key, context) // 等價于 target[key]
Reflect.set(target, key, val) // 等價于 target[key] = val