43

I have a function called "Colorbox" (jQuery plugin) that takes a number of parameters like so:

$(this).colorbox({
    width : "500px",
    height : "500px"
});

I have several different types of "this", though, each with their own properties. Like so:

var Type = {
  video: {
    width : "500px",
    height : "500px"
  },
  gallery: {
    width : "1065px",
    height : "600px"
  }
}

Beyond that, I have other behaviors, logic, and a 'default' group of settings (which get overwritten by more specific ones). What I'm trying to do is push all the appropriate settings, from multiple objects, into a single Object so I can just call:

$(this).colorbox(Settings);

How would I transfer an unknown group of properties and their values (for example "width" and "height") from something like Type.video into Settings? The goal is to be able to call Settings.height and get back the value I pushed in.

Etheryte
  • 24,589
  • 11
  • 71
  • 116
Doug Avery
  • 1,057
  • 1
  • 8
  • 14
  • 1
    possible duplicate of [How can I merge properties of two JavaScript objects dynamically?](http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically) – givanse Mar 09 '14 at 21:24
  • Please see my answer in http://stackoverflow.com/a/33572520/2934015 for caveats and an alternate solution. – Spike Sagal Nov 06 '15 at 20:32

7 Answers7

82

Take a look at the JQuery extend method. It can merge two objects together and all their properties.

From JQuery's example page:

var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);

Now settings contains the merged settings and options objects.

Community
  • 1
  • 1
Matthew Manela
  • 16,572
  • 3
  • 64
  • 66
  • This looks perfect! I guess I thought there would be a built-in javascript method for this, but Extend seems to do exactly what I need. Thanks! – Doug Avery Aug 26 '09 at 13:35
  • This seems useful to the OP but technically it's not what the question asks for. The OP didn't mentioned he wanted to use jQuery for that... Just plain JavaScript. – Alejandro García Iglesias Jul 30 '12 at 21:31
  • 8
    The OP is writing a jQuery plugin sp it would seem silly to give a more complicated solution when it would make most sense to use a jQuery function inside of a jQuery plugin. – Matthew Manela Jul 30 '12 at 22:58
13

JavaScript have a simple native function to merge object. which is Object.assign() introduced in ES6.

  // creating two JavaScript objects
    var x = { a: true };var y = { b: false}; // merging two objects with JavaScript native function
    var obj = Object.assign(x,y);
    //result
    Console.log(obj); // output is { a: true, b: false }

for more information about javascript merging object please check at merge JavaScript objects with examples.

Venu immadi
  • 1,585
  • 11
  • 20
  • Upvoted. I had to upgrade node, because of the "undefined is not a function" error - even when running node with the --harmony flag... – Herald Smit Oct 14 '15 at 17:04
  • This does not work with nested layers in objects, it only works at the top level –  Dec 19 '16 at 17:26
  • For the sake of completeness: The target of the merge is the first argument to `Object.assign`, ie. `x` in the sample code is mutated. See [here(MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) for details. – collapsar Apr 03 '18 at 14:21
12

A non-jQuery solution is:

YOUROBJ.vars = {
    vars1: {
        vars1_1: 'an object which will overwrite',
        vars1_2: 'an object which will be added'
    }
};

YOUROBJ.vars2 = (!YOUROBJ.vars) ? {} : YOUROBJ.vars;

YOUROBJ.vars = {
    vars1: {
        vars1_1: 'an object which will be overwritten',
        vars1_3: 'an object which will remain'
    }
};

YOUROBJ.extend = function(obj, defaults) {
    for (var i in defaults) {
        if (!obj[i]) {
            obj[i] = defaults[i];
        } else {
            YOUROBJ.extend(obj[i], defaults[i]);
        }
    }
};
YOUROBJ.extend(YOUROBJ.vars, YOUROBJ.vars2);
delete YOUROBJ.vars2;

This is useful if you wish to add a variable to a general functions object before it has been loaded and created.

This also enables the second YOUROBJ.vars to act as the default setting,.

mummybot
  • 2,668
  • 2
  • 28
  • 31
6

If you're using jQuery you should checkout the $.extend function.

You could try something like this:

$.fn.somePlugin = function(options){
  settings = $.extend(true, {default_values: "foo"}, options);
}
4

I have also created a "merge" function in Javascript to use for my general purposes:

if (typeof Object.merge !== 'function') {
    Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
        for(var i in o2) { o1[i] = o2[i]; }
        return o1;
    };
} 

Usage:

var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});

It's quicker and dirtier (shallow copy), but it does what I need it to do.

palswim
  • 11,856
  • 6
  • 53
  • 77
  • Warning: extending the Object prototype like that is unadvisable and generally dangerous. Pretty good writeup on the dangers of this and when/how you can get away with it here http://sugarjs.com/native and a great talk on the subject here http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542 – timoxley Jul 31 '12 at 17:24
  • 3
    @timoxley: If you look closely, it isn't actually modifying the Object prototype. – palswim Jul 31 '12 at 17:58
3

I don't understand your question very well but i think you should use the $.extend function:

Settings=$.extend(Settings, Type.video);

in this way Settings will get Type.video properties

mck89
  • 18,918
  • 16
  • 89
  • 106
1

Simply first level merging (appending keys from second object to first one):

var mergeObjects = function (originalObject, objectToAppend) {
    for (var item in objectToAppend) {
        if (objectToAppend.hasOwnProperty(item)) {
            originalObject[item] = objectToAppend[item];
        }
    }
};

originalObject must be non-null!

user11153
  • 8,536
  • 5
  • 47
  • 50
  • In what case would hasOwnProperty trigger a false result in the check? Is there additional items that the foreach loop will extract out of the object? – Prusprus Jul 10 '14 at 15:02
  • 1
    @Prusprus *["The use of hasOwnProperty() prevents the loop from enumerating over any inherited properties on the object"](http://brianflove.com/2013/09/05/javascripts-hasownproperty-method/)* – user11153 Jul 10 '14 at 17:31
  • That's a good reference, thanks for that. So I guess I'm a little confused as to how an array (say in the example given thru your URL) can have inherited properties, if it's just an array? – Prusprus Jul 10 '14 at 17:35
  • 1
    @Prusprus Every array inherits properties added to [`Array.prototype`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype): *"`Array` instances inherit from `Array.prototype`. As with all constructors, you can change the constructor's prototype object to make changes to all `Array` instances."* – user11153 Jul 10 '14 at 17:45