0

I have this object bellow :

let 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)
  }
}

so to calculate any number i simply do method chaining like bellow

calc.num(5).add().sub().show()
//output: 7

Problem: i was thinking if there is a way to replace the object property name from an array then execute it , look at this code bellow

// it supose to replace the items on the array then execute the object calls
let arr = [calc.add(), calc.sub(), calc.show()]

calc.num(5).arr[0].arr[1].arr[2]// <-- this will be translated

calc.num(5).add().sub().show()  // <-- to this

i know that it tries to find arr[n] in the object and it will throw an error (undefined)

.. i want to achieve this specific case in any way guys OR similar solutions OR infos

Thank you in advance :)

4
  • No, you can't do anything like that. You need () to call a function. The closest you could do is to define arr as a getter that returns an array of functions, but you'd still have to write .arr[0]() Commented Apr 5, 2021 at 5:34
  • Why do you want to do this? Commented Apr 5, 2021 at 5:34
  • Why does arr[0] correspond to add() rather than num()? Commented Apr 5, 2021 at 5:37
  • its just an simplified example , and the why? i posted a question before and i didn't get any answer .. stackoverflow.com/questions/66895602/… Commented Apr 5, 2021 at 7:47

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.