Reputation: 600
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?
Upvotes: 5
Views: 6123
Reputation: 89254
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());
Upvotes: 10