What is a Proxy?

// pOjb is a Proxy object created by new Proxy
var pObj = new Proxy(obj, handlers)
Copy the code

Why are proxy objects needed

Here’s an example of bookkeeping:

// Obj is for us, wallet is for our wallet, now we have $100 in our wallet
// consume refers to the number of consumption, each consumption plus 1, a record
var obj = {wallet: 100}
var consume = 0

// This month, we drank fat house happy water five times, and we made a note of each consumption

// It's 3 yuan today
consume++
obj.wallet = 97

// It's 3 yuan today
consume++
obj.wallet = 94

// It's 3 yuan today
consume++
obj.wallet = 91

// It's 3 yuan today
consume++
obj.wallet = 88

// It's 3 yuan today
consume++
obj.wallet = 85
Copy the code

Each time we modify the remaining amount of the wallet, we need to perform a conme ++ to perform an accounting operation. Is there an easier way to increase consumption without having to write a line of code every time?

Yes, it is a Proxy object! With a proxy object, you want to change all the properties of the target object to the same properties of the proxy object. The proxy object provides the interception of properties such as [[get]] modify [[set]]. Js calls this interception a trap.

With the catcher, we can capture the timing of operations on properties in our code, allowing us to execute our custom business logic code first. Because we change the property operation on the target object to the same property operation on the proxy object, we need to perform the original operation on the target object through Reflact at the end.

var consume = 0
// Target object
var obj = {wallet: 100}
// Trap trap
var handlers = {
	set(target, key, val) {
		// target Target object
		// The property of the proxy object to be modified
		
		// Record a purchase
		consume++
		// Trigger the property operation of the original target object through the Reflact object
		// Target [key] = val
		Reflect.set(target, key, val)
	}
}
// Proxy object
var pObj = new Proxy(obj, handlers)
// Change the property Wallet operation on the target object obj to the same property Wallet operation on the proxy object
pObj.wallet = 97
pObj.wallet = 94
pObj.wallet = 91
pObj.wallet = 88
pObj.wallet = 85

console.log(obj.wallet) / / 85
console.log(consume) / / 5
Copy the code

How to Cancel an agent

If, one day, you’re financially free and don’t need to keep track of every purchase you make, you may need to cancel your proxy. The code is simple:

var consume = 0
var obj = {wallet:  100}
var handlers = {
	set(target, key, val) {
		consume++
		Reflect.set(target, key, val)
	}
}

// Use proxy.revocable to create a Proxy
var tmpObj = Proxy.revocable(obj, handlers)
var pObj = tmpObj.proxy
var prevoke = tmpObj.revoke

// Use proxy objects for consumption billing
pObj.wallet = 97
pObj.wallet = 94
pObj.wallet = 91

// One day, we achieved a small goal
pObj.wallet = 100000000
// We do not need to account, we need to cancel the agent created
prevoke() // Execute prevoke, it is as simple as that

pObj.wallet = 99999997 // A TypeError error was reported.
Copy the code

Proxy post-pattern

In the previous examples, the business logic in the proxy capture is executed first, and then the properties of the target object are performed through Reflect. This mode of capturing code comes first, and the mode of the target object comes later is called the “proxy first” mode.

Of course, the “proxy after” mode here does not use the Reflect object to trigger the target object property operation first, and then execute the other operation code in the catcher. Instead, it refers to the proxy as a complement to the target object, which we still operate on, but only when some operation is not possible on the target object.

Etc., when some operation target object is not available, JS will look up the prototype of the target object, so “proxy after” mode is to proxy the prototype of the target object!

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)
	}
}

// Set catchall to greeter's prototype
Object.setPrototypeOf(greeter, catchall)

greeter.speak() // hello someone
greeter.speak('world') // hello world

// Execute a method that does not exist on greater
greeter.everyone() // hello everyone!
Copy the code

Reflect

The Reflect object is used to trigger the target object to perform the action. It’s as simple as that!

Reflect.get(target, key, context) // Equivalent to target[key]
Reflect.set(target, key, val) // target[key] = val
Copy the code