Sometimes it makes sense to add additional properties to a result of a function,

Examples could be enhancing an operation result with some meta data, extending with a timestamp, run time, etc,

Using ES6, we could easily achieve this by:

bindData(oper, props) {
  if (typeof oper === 'function') {
    return (...args) => ({
      ...oper(...args),
      ...props
    });
  }
  if (typeof oper === 'object') {
    return Object.keys(oper).reduce((prev, key) => ({
      ...prev,
      [key]: bindData(oper[key], props)
    }), {});
  }
  return oper;
}

Here are some clarifications:

  1. If oper is a function, we decorate the original function by a closure, return (...args) is the closure (read more about the spread operator.

In general, myFunction(...args); is equelevent to (args) { oper.apply(null, args); },

  1. When the returned function is invoked, the result of the original function ...oper(...args) is then merged with the props object, in other words:

...oper(), ...props is equelevent to: Object.assign({}, oper(), props); Read more about Object.assign

  1. If oper is an object, we bind each of its key’s recursively (assuming each property is a function).