1

I've searched around SO a bit and can't find any solutions that seem to do what I'm trying to do. I have two objects with the some of the same properties.

this.defaultEvents = {
    [FOCUS]: (e) => {
        this.focusHandler(e);
    },
    [BLUR]: (e) => e
};

this.otherEvents = {
    [FOCUS]: (e) => {
        this.otherFocusHandler(e);
    }
}

I want to be able to merge these properties, so that somehow I get something like this...

this.mergedEvents = {
    [FOCUS]: (e) => {
        this.focusHandler(e);
        this.otherFocusHandler(e);
    },
    [BLUR]: (e) => e
};

So that I can invoke (e) => this.mergedEvents[FOCUS](e) and have both focus handlers be called with the same arguments.

This question seems to be the closest thing to what I'm trying to do. I guess a call to each function should work?

Extend a function - merge two functions?

This temporary solution seems to work, but I guess I should be using call or apply? I'm not too familiar with either of them.

const merged = {};

for(let key in defaultEvents) {

  if ( otherEvents.hasOwnProperty( key ) && typeof otherEvents[key] === 'function') {
    merged[key] = function(e) {
      defaultEvents[key](e);
      otherEvents[key](e);
    }
  }

}

merged[FOCUS]('test');

here's a code pen too

4
  • Short of doing some weird stuff with eval, there's not really a way to add stuff to an existing function. I think your best bet is to just have a function that calls two other functions... Commented Nov 4, 2016 at 19:45
  • Could you not create an object with an event handler registration method similar to addEventListener that accepts a callback? Commented Nov 4, 2016 at 19:48
  • If you want to "merge" n functions, you have to create a new function that calls the n functions. Commented Nov 4, 2016 at 19:53
  • Thanks, gonna go with the event handler registration idea. Simpler and more to the point of what I actually want to do. Commented Nov 4, 2016 at 20:17

3 Answers 3

2

You can iterate keys of object and create composed functions for each key, e.g.:

function merge(...events) {
  const all = events
    .map(e => Object.keys(e)) // map keys
    .reduce((a, b) => [...a, ...b], []); // flatten
  const unique = [...new Set(all)]; // remove duplicates
  return unique.reduce((r, key) => {
    const handlers = events
      .filter(e => e[key]) // filter out not relevant handlers
      .map(e => e[key]); // extract concrete handler
    r[key] = e => handlers.map(h => h(e)); // compose functions with map
    return r;
  }, {});
}
Sign up to request clarification or add additional context in comments.

1 Comment

this is really cool but, I think @Scott Marcus nailed it with the event handler registration method idea. I'm gonna go with something like that. I'll mark this as an accepted answer since it actually does what I was imagining. thanks.
1

I have the same case, this is my code in Typescript:

export function mergeFunctions(...funcs) {
    return function(...args) {
        funcs.filter((fn) => !!fn).forEach(fn => fn?.(...args))
    }
}

Usage in your case:

mergeFunctions(focusHandler, otherFocusHandler)

Comments

-1

You can use .toString(), .replace(), eval()

var obj = {[`FOCUS`]: (e) => {
  console.log("abc")
}};

var mergedEvents = {
  [`FOCUS`]: (e) => {
    console.log(123)
  }
}

var fn = mergedEvents["FOCUS"].toString()
         .replace("console.log(123)", "console.log(123);console.log('abc')");

mergedEvents["FOCUS"] = eval(fn);

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.