5

I have the class:

class Course {
  constructor(name) {
    this._name = name;
  }

  getName() {
    return this._name;
  }
}

I want to create a proxy around class Course, that will return only non-private fields and methods:

const handlers = {
  get: (target, prop, reciever) => {
    if (prop in reciever && prop[0] !== '_' ) {
      if (typeof reciever[prop] === 'function') {
        return reciever[prop].apply(reciever);
      } else {
        return reciever[prop];
      }
    } else {
      throw new Error('problem');
    }
  }
}

const protect = (obj) => {
  return new Proxy(obj, handlers);
}

But when i call object method:

const protectedCourse = protect(new Course('Test'));
console.log(protectedCourse.getName()); // The expected result is - "Test"

I got the error:

  if (prop in reciever && prop[0] !== '_' ) {
    ^

RangeError: Maximum call stack size exceeded
    at Object.get (file:///usr/src/app/protect.js:37:5)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)
    at Object.get (file:///usr/src/app/protect.js:38:26)

How to call object method without infinity recursion in the handler of Proxy?

2
  • What's the actual error you get? Commented Nov 15, 2021 at 17:53
  • Maximum call stack size exceeded Commented Nov 15, 2021 at 17:54

1 Answer 1

10

You should access the property on target, which is the original object, instead of receiver which is the Proxy. Additionally, use bind instead of apply or call to return a function with the this value set.

Note that what you are trying to achieve with a Proxy can be done with private class fields.

class Course {
  constructor(name) {
    this._name = name;
  }

  getName() {
    return this._name;
  }
}

const handlers = {
  get: (target, prop, receiver) => {
    if (prop in target && prop[0] !== '_') {
      if (typeof target[prop] === 'function') {
        return target[prop].bind(target);
      } else {
        return target[prop];
      }
    } else {
      throw new Error('problem');
    }
  }
}

const protect = (obj) => {
  return new Proxy(obj, handlers);
}

const protectedCourse = protect(new Course('Test'));
console.log(protectedCourse.getName());

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.