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?
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());