Reputation:
Implementing a function to extend object method by ES6 Proxy works but with TypeError as below:
const extendMethod = (obj) => (key) => (f) => {
const handler = {
get: (target, propKey, receiver) => {
const targetValue = Reflect.get(target, propKey, receiver);
return key === propKey
? f(target.valueOf())
: (typeof targetValue === "function")
? (...args) => Object(target.valueOf())[propKey](...args)
: targetValue;
}
};
return new Proxy(obj, handler);
};
const a = { x: 5 };
const f = (target) => { console.log(target); };
const a1 = extendMethod(a)("log")(f);
a1.log(); //{x:5}
//TypeError: a1.log is not a function
How to modify the code to avoid the error? thanks.
Upvotes: 0
Views: 57
Reputation: 370809
The script is expecting a1.log
to evaluate to a function because it proceeds to get called as a1.log();
. But with the line
? f(target.valueOf())
, the f
function is run, and the output of calling f
is then returned to the outside. But the output of f
is undefined
, because the (outer) f
doesn't return anything.
One way to suppress the error would be to return a function that doesn't do anything:
? (f(target.valueOf()), () => void 0)
const extendMethod = (obj) => (key) => (f) => {
const handler = {
get: (target, propKey, receiver) => {
const targetValue = Reflect.get(target, propKey, receiver);
return key === propKey
? (f(target.valueOf()), () => void 0)
: (typeof targetValue === "function")
? (...args) => Object(target.valueOf())[propKey](...args)
: targetValue;
}
};
return new Proxy(obj, handler);
};
const a = { x: 5 };
const f = (target) => { console.log(target); };
const a1 = extendMethod(a)("log")(f);
a1.log(); //{x:5}
Or you might simply access the a1.log
property (calling the function as a side effect) and not invoke it:
const extendMethod = (obj) => (key) => (f) => {
const handler = {
get: (target, propKey, receiver) => {
const targetValue = Reflect.get(target, propKey, receiver);
return key === propKey
? f(target.valueOf())
: (typeof targetValue === "function")
? (...args) => Object(target.valueOf())[propKey](...args)
: targetValue;
}
};
return new Proxy(obj, handler);
};
const a = { x: 5 };
const f = (target) => { console.log(target); };
const a1 = extendMethod(a)("log")(f);
a1.log; //{x:5}
If the outer f
function did return a function (that is, if it was a higher-order function), then you would be able to use a1.log()
normally:
const extendMethod = (obj) => (key) => (f) => {
const handler = {
get: (target, propKey, receiver) => {
const targetValue = Reflect.get(target, propKey, receiver);
return key === propKey
? f(target.valueOf())
: (typeof targetValue === "function")
? (...args) => Object(target.valueOf())[propKey](...args)
: targetValue;
}
};
return new Proxy(obj, handler);
};
const a = { x: 5 };
const f = (target) => {
console.log(target);
return arg => {
console.log('inner fn! ' + arg);
};
};
const a1 = extendMethod(a)("log")(f);
a1.log('foo');
Upvotes: 2