So I have a class XYZ in JavaScript, it has few functions:
class XYZ{
constructor(){
this.text=null;
}
f1(){
// Do Something
return this;
}
f2(){
// Do Something
return this;
}
f3(txt=null){
if(txt){
this.text=txt;
this.show();
}
// Do Something
return this;
}
show(){
console.log(this.text)
}
}
const obj = new XYZ();
obj.f1().f2().f3("Hello").f1();
obj.f1().f2().f3().f2();
What I want to achieve is that if there is no text to pass to f3, I want to skip the brackets and use it like a getter:
const obj = new XYZ();
obj.f1().f2().f3("Hello").f1();
obj.f1().f2().f3.f2();
I can achieve something similar like this using getter and setter, but I don't want to break the chain calling. Is there a way where we can skip braces if not passing a value, or using the same name getter and method together? Thanks
You can use Proxy
to redirect getters invoked on methods back to the instance with another Proxy
. If a method's getter is invoked (like f1.f2
) - call the method (f1
):
class XYZ {
constructor() {
this.text = null;
const handler = {
get(_, prop) {
if (typeof instance[prop] === 'function') {
const out = new Proxy(function(...args) {
return instance[prop].call(proxy, ...args);
}
, {
get(){
// the next chained method is requested, so call the current method
out();
return handler.get(...arguments);
}
});
return out;
}
return instance[prop];
}
};
const instance = this;
const proxy = new Proxy(this,handler);
return proxy;
}
f1() {
this.log('f1');
return this;
}
f2() {
this.log('f2');
return this;
}
f3(txt=null) {
if (txt) {
this.text = txt;
this.show();
}
this.log('f3');
return this;
}
show() {
console.log(this.text)
}
log(name){
console.log('calling', name + '()', 'on', JSON.stringify(this));
}
}
const obj = new XYZ();
obj.f1.f2.f3("Hello").f1.show();
const obj2 = new XYZ();
obj2.f1.f2.f3.f2.show();
.as-console-wrapper { top: 0; max-height: 100% !important; }