Instead of using array indexes to try and build up your chain of method calls, you could make an array of function references (ie: uncalled functions, that can then later be called):
let arr = [calc.add, calc.sub, calc.show]; // no `()` after each method
using this, you can then use .reduce() with .call() to bind the this based on the previous function call, for example;
const calc = { data: null, num: function(x) { this.data = x; return this }, add: function() { this.data += 4; return this }, sub: function() { this.data -= 2; return this }, show: function() { console.log(this.data) } };
const arr = [calc.add, calc.sub, calc.show];
arr.reduce((prev, fn) => fn.call(prev), calc.num(5));
// number to start with --------------------/\
Or, instead, you might extract .show() and then call that manually yourself, that way you can call any other methods that might not be included in your array of methods:
const calc = { data: null, num: function(x) { this.data = x; return this }, add: function() { this.data += 4; return this }, sub: function() { this.data -= 2; return this }, show: function() { console.log(this.data) } };
const arr = [calc.add, calc.sub];
const res = arr.reduce((prev, fn) => fn.call(prev), calc.num(5));
res.show(); // call any other methods not in `arr`
This could be adapted to use a wrapper function if your functions take arguments, for example:
// add: function(x) {} <--- takes x as an argument and adds it to num/data.
const calc = { data: null, num: function(x) { this.data = x; return this }, add: function(x) { this.data += x; return this }, sub: function() { this.data -= 2; return this }, show: function() { console.log(this.data) } };
const arr = [function() {
return calc.add.call(this, 4); // <--- supply argument after `this` (eg: 4)
}, calc.sub, calc.show];
arr.reduce((prev, fn) => fn.call(prev), calc.num(5));
or, a similar adaption might be to create an object as each element, and specify the arguments (if any) in an array (this imo is a little cleaner as you don't need to use the function keyword everywhere):
// add: function(x) {} <--- takes x as an argument and adds it to num/data.
const calc = { data: null, num: function(x) { this.data = x; return this }, add: function(x) { this.data += x; return this }, sub: function() { this.data -= 2; return this }, show: function() { console.log(this.data) } };
const arr = [{fn: calc.add, args: [4]}, {fn: calc.sub, args: []}];
const res = arr.reduce((prev, {fn, args}) => fn.apply(prev, args), calc.num(5));
res.show();
()to call a function. The closest you could do is to definearras a getter that returns an array of functions, but you'd still have to write.arr[0]()arr[0]correspond toadd()rather thannum()?