-1

i have arrays like this: ['req','changepage'] or like this: ['dashboard','draw','ovreview']

the result i need is:

mainObject.req.changepage()

and

mainObject.dashboard.draw.overview()

I know that i can do:

mainObject.[array[0]].[array[1]]()

but the length of the array may vary... how to do that programatically?

3 Answers3

2

You can trivially access a property using reduce:

array.reduce((o, p) => o[p], mainObject)

but to make a method call on the right context object, you need to spare the last property access:

const methodname = array.pop();
array.reduce((o, p) => o[p], mainObject)[methodname]();

Alternatively, use slice if you don't want to mutate the array.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • @MaheerAli Otherwise [the `this` keyword in the method doesn't work](https://stackoverflow.com/q/3127429/1048572) – Bergi Jul 22 '19 at 20:01
  • no need to pop in advance, the result is a function and the parentheses is the needed call. savind the last key is necessary for assigning a value to it. – Nina Scholz Jul 22 '19 at 21:06
  • 1
    @NinaScholz It's also necessary for calling the method as a method, with the object as the context. Otherwise, `reduce` returns a plain function that would be called with an `undefined` thisArg. – Bergi Jul 22 '19 at 21:11
1

Besides, Array.reduce, you could just use a loop.

let path = ['first', 'second', 'method'];

let target = {
  first: {
    second: {
      value: 'success',
      method: function(msg) {
        console.log(msg + this.value);
      }
}}};

let result = target;
for (let key of path.slice(0, -1)) {
    result = result[key];
}
result[path.slice(-1)]('result: ') // prints 'result: success'

As Bergi alludes to in their answer, the Array.slice calls (or a use of Array.pop) are needed if the function being called might ever reference this. In my example above, if you just use let key of path, then call result('result: '), the output will be result: undefined.

jirassimok
  • 2,386
  • 1
  • 11
  • 17
0

.reduce is useful for that:

  array.reduce((acc, key) => acc[key], mainObject)();

Or written using a plain for loop:

  let acc = mainObject;

  for(const key of array)
     acc = acc[key];

  acc();
Jonas Wilms
  • 106,571
  • 13
  • 98
  • 120