Proxies

To create a proxy object, we use the Proxy constructor -new Proxy();. The proxy constructor takes two items:

  • the object that it will be the proxy for
  • an object containing the list of methods it will handle for the proxied object

The second object is called thehandler.

A Pass Through Proxy

The simplest way to create a proxy is to provide an object and then an empty handler object.

var richard = {status: 'looking for work'};
var agent = new Proxy(richard, {});

agent.status; // returns 'looking for work'

The above doesn't actually do anything special with the proxy - it just passes the request directly to the source object! If we want the proxy object to actually intercept the request, that's what the handler object is for!

The key to making Proxies useful is the handler object that's passed as the second object to the Proxy constructor. The handler object is made up of a methods that will be used for property access. Let's look at theget:

Get Trap

Thegettrap is used to "intercept" calls to properties:

const richard = {status: 'looking for work'};
const handler = {
    get(target, propName) {
        console.log(target); // the `richard` object, not `handler` and not `agent`
        console.log(propName); // the name of the property the proxy (`agent` in this case) is checking
    }
};
const agent = new Proxy(richard, handler);
agent.status;     // logs out the richard object (not the agent object!) and 
                  //the name of the property being accessed (`status`)

In the code above, thehandlerobject has agetmethod (called a "trap" since it's being used in a Proxy). When the codeagent.status;is run on the last line, because thegettrap exists, it "intercepts" the call to get thestatusproperty and runs thegettrap function. This will log out the target object of the proxy (therichardobject) and then logs out the name of the property being requested (thestatusproperty). And that's all it does! _It doesn't actually log out the property! This is important -_if a trap is used, you need to make sure you provide all the functionality for that specific trap.

위의 코드에서 handler 객체에는 get 메소드가 있습니다 (Proxy에서 사용되기 때문에 "trap"이라고 함). 코드 agent.status;get 트랩이 존재하기 때문에 마지막 라인에서 실행되며, 호출을 가로채어 status 속성을 가져오고 get 트랩 기능을 실행합니다. 그러면 Proxy의 대상 객체 (richard 객체)가 로그 아웃되고 요청된 속성의 이름 (status 속성)이 로그 아웃됩니다. 그게 전부입니다! 실제로 로그 아웃하지 않습니다! 이것은 중요합니다. trap을 사용하는 경우 특정 trap에 대한 모든 기능을 제공해야합니다.

Accessing the Target object from inside the proxy

If we wanted to actually provide the real result, we would need to return the property on the target object:

const richard = {status: 'looking for work'};
const handler = {
    get(target, propName) {
        console.log(target);
        console.log(propName);
        return target[propName];
    }
};
const agent = new Proxy(richard, handler);
agent.status; // (1)logs the richard object, (2)logs the property being accessed, (3)returns the text in richard.status

Notice we added thereturn target[propName];as the last line of thegettrap. This will access the property on the target object and will return it.

Having the proxy return info, directly

Alternatively, we could use the proxy to provide direct feedback:

const richard = {status: 'looking for work'};
const handler = {
    get(target, propName) {
        return `He's following many leads, so you should offer a contract as soon as possible!`;
    }
};
const agent = new Proxy(richard, handler);
agent.status; // returns the text `He's following many leads, so you should offer a contract as soon as possible!`

With this code, the Proxy doesn't even check the target object, it just directly responds to the calling code.

So thegettrap will take over whenever any property on the proxy is accessed. If we want to intercept calls to_change_properties, then thesettrap needs to be used!

Thesettrap is used for intercepting code that will change a property. Thesettrap receives: the object it proxies the property that is being set the new value for the proxy

const richard = {status: 'looking for work'};
const handler = {
    set(target, propName, value) {
        if (propName === 'payRate') { // if the pay is being set, take 15% as commission
            value = value * 0.85;
        }
        target[propName] = value;
    }
};
const agent = new Proxy(richard, handler);
agent.payRate = 1000; // set the actor's pay to $1,000
agent.payRate; // $850 the actor's actual pay

In the code above, notice that thesettrap checks to see if thepayRateproperty is being set. If it is, then the proxy (the agent) takes 15 percent off the top for her own commission! Then, when the actor's pay is set to one thousand dollars, since thepayRateproperty was used, the code took 15% off the top and set the actualpayRateproperty to850;

Other Traps

So we've looked at thegetandsettraps (which are probably the ones you'll use most often), but there are actually a total of 13 different traps that can be used in a handler!

  1. the get trap lets the proxy handle calls to property access
  2. the set trap lets the proxy handle setting the property to a new value
  3. the apply trap lets the proxy handle being invoked (the object being proxied is a function)
  4. the has trap lets the proxy handle the using in operator
  5. the deleteProperty trap lets the proxy handle if a property is deleted
  6. the ownKeys trap lets the proxy handle when all keys are requested
  7. the construct trap lets the proxy handle when the proxy is used with the new keyword as a constructor
  8. the defineProperty trap lets the proxy handle when defineProperty is used to create a new property on the object
  9. the getOwnPropertyDescriptor trap lets the proxy handle getting the property's descriptors
  10. the preventExtenions trap lets the proxy handle calls to Object.preventExtensions() on the proxy object
  11. the isExtensible trap lets the proxy handle calls to Object.isExtensible on the proxy object
  12. the getPrototypeOf trap lets the proxy handle calls to Object.getPrototypeOf on the proxy object
  13. the setPrototypeOf trap lets the proxy handle calls to Object.setPrototypeOf on the proxy object

As you can see, there are a lot of traps that let the proxy manage how it handles calls back and forth to the proxied object.

results matching ""

    No results matching ""