1

So I'm using $.extend to combine multiple components (objects). Some of these components have a function with the same key. I want the final extended object to have that same key, but have it point to a function which calls all of the merged components' versions of the functions one after the other.

So it'd look something like this:

var a = { foo: function() { console.log("a"); } };
var b = { foo: function() { console.log("b"); } };
var c = {}; // Doesn't have foo

var d = $.extend({}, a, b, c);
var e = $.extend({}, a, c);
var f = $.extend({}, c);

d.foo(); // Should call function() { console.log("a"); console.log("b"); }
e.foo(); // Should call function() { console.log("a"); }
f.foo(); // Should call function() {}

Is there a pragmatic way of doing this? I only want to do this for a specific set of keys, so I would only want to merge those specific keys' functions together and let the ordering in extend overwrite anything else.

Hopefully that makes sense :S

2 Answers 2

1

Note

f.foo(); // Should call function() {}

object c does not appear to have property foo . callling f.foo() returns TypeError: undefined is not a function . Not certain if requirement to add foo function to extended f object , or return object c (empty object) from anonymous function ? At piece below , foo function not added to extended f object.

jquery $.Callbacks() utilized to add functions having foo property at $.each()

Try

var a = { foo: function() { console.log("a"); } };
var b = { foo: function() { console.log("b"); } };
var c = {}; // Doesn't have foo

//d.foo(); 
// Should call function() { console.log("a"); console.log("b"); }
//e.foo(); 
// Should call function() { console.log("a"); }
//f.foo(); 
// Should call function() {}

var callbacks = $.Callbacks();
var arr = [], d, e, f;
$.each([a,b,c], function(k, v, j) {
  var j = [a,b,c];
  // filter objects having `foo` property
  if (v.hasOwnProperty("foo")) {
    arr.push([v, v.foo]);
    if (arr.length > 1) {
       callbacks.add(arr[0][1], arr[1][1]);
       // `add` `foo` properties to `callbacks`
       // `fire` both `callbacks` when `object.foo` called
       j[k -1].foo = callbacks.fire;
       d = $.extend({}, j[k - 1])
    } else {
       // `else` extend original data (`fn`, `object`) 
       // contained within object 
       e = $.extend({}, j[k + 1]);
       f = $.extend({}, j[++k + 1]);
    }
  }  
});

d.foo(); // `a` , `b`
e.foo(); // `b`
console.log(f); // `Object {}`
f.foo() // `TypeError: undefined is not a function`

jsfiddle http://jsfiddle.net/guest271314/3k35buc1/

See jQuery.Callbacks()

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

1 Comment

Thanks! I'd like to be able to call foo on the returned object regardless of if the components contained it. I'll have to look more in depth at your answer, but it seems like I could use your solution but just add a dummy function foo in the case where it doesn't exist in v.
0

Here's what I ended up with based off of guest271314's answer. toMix is the array of components to be mixed into the object. I actually didn't need the dummy functions I thought I might, and I ended up using an array of functions instead of the $.Callbacks() so that I could control the order in which the functions are called. I also needed to use the call() function so that I could call the functions from the correct this object.

this.functionMerge = function(toMix) {
  var callbacks = {};
  var functions = {};
  var obj = {};
  var keys = [
    'componentWillMount',
    'componentDidMount',
    'componentWillUpdate',
    'componentDidUpdate',
    'componentWillUnmount'
  ]

  $.each(keys, function(key, value) {
    callbacks[value] = [];
  });

  for (i = 0; i < toMix.length; ++i) {
    $.each(keys, function(key, value) {
      if (toMix[i].hasOwnProperty(value) && typeof toMix[i][value] == 'function') {
        callbacks[value].push(toMix[i][value]);
      }
    });
    $.extend(true, obj, toMix[i]);
  }

  $.each(keys, function(key, value) {
    functions[value] = function() {
      var that = this;
      $.each(callbacks[value], function(key, value) {
        value.call(that);
      });
    };
  });

  return $.extend(true, obj, functions);
}

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.