Andrew
Andrew

Reputation: 1998

jQuery extend multiple objects with the same function

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

Upvotes: 1

Views: 1071

Answers (2)

Andrew
Andrew

Reputation: 1998

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);
}

Upvotes: 0

guest271314
guest271314

Reputation: 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()

Upvotes: 1

Related Questions