2

I'm using JavaScript's Proxy object to create a get() handler to trap property access to an instance of a class.

I would like to have different behavior depending on whether the Proxy is being called by methods within the class or by the proxy itself.

Is that possible?

EDIT: Some example code that hopefully explains what I'm trying to do:

class Something {
  constructor() {
    this.prop1 = 'val1';
    this.prop2 = 'val2';
  }

  getProp() {
    return this.prop1;
  }
}

const instance = new Something();

const proxiedObject = new Proxy(instance, {
  get: function(target, property, receiver) {
    if (WHATEVER_IS_ACCESSING_THIS_IS_NOT_AN_INSTANCE_METHOD) {
      return false;
    }
    else {
      return target[property];
    }
  }
});

console.log(proxiedInstance.getProp()); // 'val1'
console.log(proxiedInstance.prop1);     // 'false'
jdelman
  • 683
  • 1
  • 6
  • 20

1 Answers1

4

I guess the simplest solution would be to bind all methods when they are accessed on the proxy, so that any accesses to this won't even go through the proxy:

const proxiedObject = new Proxy(instance, {
  get: function(target, property, receiver) {
    const val = target[property];
    if (typeof val == "function") // you need this anyway for `proxiedObject.getProp()`
      return val.bind(target);
    else
      return false;
  }
});

Of course there are lots of other ways to wrap the getProp method (or any other methods) so that during its execution the proxy will become transparent for property accesses.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • thank you so much! savior! :) I looked for it the whole evening and only now here found the solution. Now to understand how it works.. and can you please also list some of those lots of other ways? Thank you! – Olga Farber Jun 29 '21 at 23:24
  • @OlgaFarber I guess I was thinking of things like `return function (...args) { try { isMethodCall = true; return val.apply(this, args); } finally { isMethodCall = false; } }` with a global `let isMethodCall` flag which you can test in the way the OP imagined. Of course you'd have to guard against reentrancy and all kinds of things that could go wrong with this… – Bergi Jun 29 '21 at 23:38
  • @OlgaFarber Another way might be to `return val.bind(new Proxy(instance, {...handlers, isInstanceMethod: true}))`, where the `this` in the method calls will refer to a different (but similar) proxy whose handlers will be more transparent than the original ones, based on the `isInstanceMethod` flag. – Bergi Jun 29 '21 at 23:41