Piping function in JavaScript – Part 1

Given an object which can have a function as a value at a nested level, create a function that will accept arguments as input and pass it through all the functions in the input object and return the computed value.

Example

Input:
{
  a : {
    b : (a,b,c) => a+b+c,
    c : (a,b,c) => a+b-c,
  },
  d : (a,b,c) => a-b-c
}

Fn(obj)(1,1,1);

Output:
{
  a : {
    b : 3,
    c : 1
  },
  d: -1
}

We can solve this by forming a closure, creating a function that will accept the object as input, and from this function returning another function that will accept the arguments.

Inside the inner function. Iterate all the keys of the object, if the value of the key is a function, pass the arguments to it and store its computed value on that key. Else recursively call the same function for nested processing.

At the end return the original input object as we are doing the processing in-place.

const pipe = (obj) => {
  // return another function that will accept all the args
  return function(...args){
    // iterate the keys of the object
    for (let key in obj) {
        // get the value
        let val = obj[key];
      
        // if the value is a function
        if (typeof val === 'function') {
            // pass the args to the function
            // store the result on the same key
            obj[key] = val(...args);
        }
        else {
            // else recursively call the same function
            // if it is nested object it will be further processed
            obj[key] = pipe(val)(...args);
        }
    }
    
    // return the input after processing
    return obj;
  }
};
Input:
let test = {
    a: {
        b: (a, b, c) => a + b + c,
        c: (a, b, c) => a + b - c,
    },
    d: (a, b, c) => a - b - c,
    e: 1,
    f: true
};

console.log(pipe(test)(1, 1, 1));

Output:
{
  "a": {
    "b": 3,
    "c": 1
  },
  "d": -1,
  "e": 1,
  "f": true
}