How do I call a function when reading a property of an object?

We can use this pattern to create hooks when reading a property from an object:

const obj = {};

Object.defineProperty(obj, 'x', {
    get: function () {
      return require('x');
    }
});

      

I am wondering if there is a way to create a hook when reading any properties of an object like obj?

For example, when code tries to access property "y" that doesn't already exist on obj

, the hook will still be called.

This is the key part: if I knew all the properties of an object ahead of time, I could iterate over them. But in this case, properties can be added to the object later, or an unexpected property can be read (the end user will trigger something unexpected.)

+3


source to share


2 answers


I think what you are looking for Proxy

is a new feature in ECMAScript 2015 and allows you to define certain behavior for certain internal methods like getting properties. The hook implementation handler.get

allows you to call a specific function whenever a resource is accessed:

const obj = {};
const proxyObj = new Proxy(obj, {
  get(target, property, receiver) {
    console.log('accessed');
  }
});
proxyObj.foobar; //A property is accessed and the console is logged to
      

Run codeHide result




Here access to any property proxyObj

will result in registration in the console. All "hook" means getting the property value is caught or hooked, and then you can invoke normal behavior when that happens. target

here is the target ( obj

), property

is the property being accessed and receiver

is the proxy. To apply it here, check if there is property

y

:

if(property === 'y') {
  ...
}

      

It doesn't matter if the property exists or not, the hook is still called. There are many other hooks you can set, such as setting a property using an operator in

, using an operator delete

, etc. You can see them all on MDN .

+3


source


@Andrew Lee beat me up, but here is a real-world example that is my use case:

// async and bluebird libraries are installed in my local project



let obj = {};

const proxy = new Proxy(obj, {
  get(target, property, receiver) {
    return require(property);
  }
});

const {async, bluebird } = proxy;
console.log('bluebird => ', bluebird);

      

now I can insert this proxy object anywhere and myself or an end user can easily access the dependencies. The goal is that you don't need to preload dependencies if you don't need them at all. It also saves a few lines of code here and there.

+1


source







All Articles