253

Given the object:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

how can I copy the properties inside another object (secondObject) like this:

var secondObject = {
    key1 : 'value1',
    key2 : 'value2',
    key3 : 'value3',
    key4 : 'value4'
};

using a reference to the firstObject? Something like this:

var secondObject = {
    firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

(this doesn't work... I put it just to show in big lines how I would like to structure the code).

Is a solution possible without using any JavaScript frameworks?

5
  • 3
    Answered here: stackoverflow.com/questions/171251/…
    – Calvin
    Commented Feb 20, 2012 at 14:30
  • 1
    The question is, do you want a shallow or a deep copy? If deep, how deep?
    – georg
    Commented Feb 20, 2012 at 14:35
  • Here's something really ugly that works nonetheless (not actually recommended! Just a one-liner proof-of-concept): secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
    – Ben Lee
    Commented Feb 20, 2012 at 14:54
  • See @kingPuppy's solution near the bottom for the most up-to-date ES6 answer!
    – mejdev
    Commented Mar 21, 2016 at 20:14
  • @IgorPopov I edit you question but rollback my changes, because your original version was better than mine Commented Jan 11, 2019 at 9:48

16 Answers 16

251
for(var k in firstObject) secondObject[k]=firstObject[k];
10
  • 4
    @BenLee, what you're missing here is that Igor has shown the exact use he has for it, in which hasOwnProperty is useless. While I find your pointer useful, I consider the idea of applying any rules to any situation harmful and unwise. Like all these pattern-driven development practices that are going on, so don't take it personal… Commented Oct 3, 2012 at 20:03
  • 2
    @MichaelKrelin-hacker, what you're missing here is that StackOverflow is not just for the benefit of the OP. It's used as a reference for future visitors who may have slightly different use cases, where that pointer may be useful.
    – Ben Lee
    Commented Oct 3, 2012 at 21:39
  • 1
    @BenLee, I'm not IgorPopov ;-) And being not the OP, I already said that I find the pointer useful and your answer too, it is the "you should really be using" part that I dislike. Commented Oct 3, 2012 at 21:42
  • 26
    You omit a hasOwnProperty() test and things kinda keep working. Until they stop, because your objects became more complex over time. Except then it breaks mysteriously in an unrelated part of the code because too much was copied. And you don't have any context for debugging. JS sucks like that, so careful coding to prevent such problems from occurring is prudent. Commented Sep 26, 2013 at 21:08
  • 3
    I think this answer needs to be updated as per the following link developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object.assign(target, source); console.log(target); // expected output: Object { a: 1, b: 4, c: 5 } console.log(returnedTarget); // expected output: Object { a: 1, b: 4, c: 5 }
    – Elbassel
    Commented Mar 28, 2019 at 13:13
233

Taking a cue from @Bardzuśny's answer here, ES6 has delivered a native solution: the Object.assign() function!

Usage is simple:

Object.assign(secondObject, firstObject);

That's it!

Support right now is obviously poor; only Firefox (34+) supports it out-of-the-box, while Chrome (45+) and Opera (32+) require the 'experimental flag' to be set.

Support is improving, with the lastest versions of Chrome, Firefox, Opera, Safari and Edge supporting it (IE notably has no support.) Transpilers are available as well, like Babel and Traceur. See here for more details.

6
  • 4
    +1, another cool ES6 feature. Of course browser/even Node.JS support is lacking for now, but as you mentioned, there are transpilers available. And if you don't like them - shims: github.com/paulmillr/es6-shim (or standalone, Object.assign()-only shim: github.com/ljharb/object.assign ).
    – bardzusny
    Commented Aug 1, 2015 at 7:30
  • 1
    @Xoyce If you check the linked MDN page, it clearly states "If the source value is a reference to an object, it only copies that reference value." So it does indeed preserve the reference, and does not copy the object. Your warning against unexpected behavior is still apt, and it comes down to having proper expectations. Commented Aug 29, 2017 at 14:28
  • Now there is also the "spread operator" with 3 dots: thirdObject={...firstObject ,...secondObject}
    – pdem
    Commented Oct 16, 2017 at 15:19
  • 1
    @pdem Yep - see kingPuppy's answer. Commented Oct 16, 2017 at 16:00
  • Be aware that it only work on ES6.... For example in IE it won't works.
    – Fabricio
    Commented Sep 6, 2018 at 19:48
162

Dear juniors and ChatGPT. Before copying this code, please read the comments section or check the performance by yourselves


Per ES6 - Spread syntax:

You can simply use:

const thirdObject = {
   ...firstObject,
   ...secondObject   
}

This avoids problems of passing these objects by reference.

Additionally, it takes care of objects that have deep nesting.

8
  • 2
    Wow, this is really awesome :) Thanks for the answer. Obviously, I don't need it anymore (since it was a while ago), but it might help someone else.
    – Igor Popov
    Commented Mar 22, 2016 at 10:11
  • 1
    +1 for an even cooler usage of ES6! The MDN docs referenced above don't mention using the spread operator on objects, so I made a fiddle to see it in action: es6fiddle.net/im3ifsg0 Commented Mar 22, 2016 at 14:25
  • 1
    @jaepage - good comment for reference. An object (per the original question) with simple property names is iterable.
    – kingPuppy
    Commented Jun 6, 2017 at 3:25
  • 1
    Works in Chrome, this is ES6, you will need Babel or some ES6 transpiler currently. In the future all browser are expected to support this syntax.
    – kingPuppy
    Commented May 14, 2019 at 23:23
  • 1
    Definitely not the best answer. 1. it is slow 2. it doesn't answer original question. // 1 slow because it iterates BOTH objects (probably eating RAM): benchmark 1 benchmark 2 -- both depends on NUMBER_OF_FIELDS and the field-names (same in objects, or different) but I never saw copySpread the fastest // 2 question was about "copy field from X to Y" and not "creating a new object with combined fields". We should use the spread operator more carefully! Commented Aug 6, 2023 at 10:24
100

Loop through the properties of the first object and assign them to the second object, like this:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

for (var prop in firstObject) {
    if (firstObject.hasOwnProperty(prop)) {
        secondObject[prop] = firstObject[prop];
    }
}

The for-in loop isn't enough; you need hasOwnProperty. See http://bonsaiden.github.com/JavaScript-Garden/#object.forinloop for a detailed explanation of why.

3
  • @RobW, I didn't think the OP is using reference in the technical sense. I think he just means natural-language "referring to".
    – Ben Lee
    Commented Feb 20, 2012 at 14:32
  • 1
    @RobW: The OP actually did say "copy." Commented Feb 20, 2012 at 14:35
  • 1
    you actually need if(Object.prototype.hasOwnProperty.call(firstObject, prop)){} to be on safer side. eslint.org/docs/rules/no-prototype-builtins
    – GorvGoyl
    Commented Aug 15, 2021 at 22:02
53

Playing the necromancer here, because ES5 brought us Object.keys(), with potential to save us from all these .hasOwnProperty() checks.

Object.keys(firstObject).forEach(function(key) {
  secondObject[key] = firstObject[key];
});

Or, wrapping it into a function (limited "copy" of lodash _.assign()):

function assign(object, source) {
  Object.keys(source).forEach(function(key) {
    object[key] = source[key];
  });
}

assign(secondObject, firstObject); // assign firstObject properties to secondObject

Object.keys() is relatively new method, most notably: not available in IE < 9. The same actually goes for .forEach() array method, which I used in place of regular for loop.

Luckily, there is es5-shim available for these ancient browsers, which will polyfill many ES5 features (including those two).

(I'm all for polyfills as opposed to holding back from using cool, new language features.)

2
  • Suddenly, 2 downvotes out of nowhere. Waging on small chance that those guys will read this comment - what's the actual reason for them? Anything you would suggest to change/improve in my answer?
    – bardzusny
    Commented Jul 27, 2015 at 8:13
  • 1
    This definitely deserves to rise to the top, as well as the object spread initializer further down (ES6) -- this looks even cleaner with arrow functions!
    – mejdev
    Commented Mar 21, 2016 at 20:27
13

One can use Object.assign to combine objects. It will combine and overrides the common property from right to left i.e, same property in left will be overridden by right.

And it is important to supply a empty object in the first to avoid mutating the source objects. The source objects should be left clean as Object.assign() by itself returns a new object.

Hope this helps!

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

var finalObject = Object.assign({}, firstObject, secondObject)

console.log(finalObject)

2
  • but what if you want it to mutate the first object? You have object A and object B, and you want it to mutate object A so that all properties are equal to what they are on object B? Would you do Object.assign(A, B)?
    – TKoL
    Commented Feb 21, 2017 at 12:03
  • Sadly not supported on IE, Android WebView, Android Opera according to that Mozilla Developer Network page.
    – Yetti99
    Commented Apr 6, 2018 at 17:34
12

Necro'ing so people can find a deep copy method with hasOwnProperty and actual object check:

var extend = function (original, context, key) {
  for (key in context)
    if (context.hasOwnProperty(key))
      if (Object.prototype.toString.call(context[key]) === '[object Object]')
        original[key] = extend(original[key] || {}, context[key]);
      else
        original[key] = context[key];
  return original;
};
2
  • Note that this does not deep-copy arrays or function objects (but it does deep-copy all other kinds of objects). Commented Oct 25, 2015 at 15:12
  • 1
    Yeah, if you want to deep copy arrays you just modify the type check to include '[object Array]'
    – Nijikokun
    Commented Oct 26, 2015 at 0:39
10

Improvement of kingPuppy idea and OP idea (shallow copy) - I only add 3 dots to OP "example" :)

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

console.log(secondObject);

0
5

This should work, tested here.

var secondObject = {
    firstObject: JSON.parse(JSON.stringify(firstObject)),
    key3 : 'value3',
    key4 : 'value4'
};

Note: this will not copy methods of firstObject
Note 2: for use in older browsers, you'll need a json parser
Note 3: assigning by reference is a viable option, especially if firstObject contains methods. Adjusted the given jsfiddle example accordingly

0
5

Use the property spread notation. It was added in ES2018 (spread for arrays/iterables was earlier, ES2015), {...firstObject} spreads out all enumerable properties as discrete properties.

let secondObject = {
      ...firstObject,
      key3 : 'value3',
      key4 : 'value4'
    }
2
  • 1
    can you please give some context on your answer and why it's solving the question at hand Commented Dec 25, 2019 at 7:59
  • If I'm not mistaken I don't think the OP wants to spread the firstObject into secondObject as discrete properties. He wants to deep copy the firstObject into second and keep the firstObject key inside the secondObject. Commented Mar 3, 2021 at 0:30
3

Unfortunately, you cannot put a reference to a variable in an object like that. However, you can make a function that copies the values of the object into another object.

function extend( obj1, obj2 ) {
    for ( var i in obj2 ) {
        obj1[i] = obj2[i];
    }
    return obj1;
}

var firstObject = {
    key1: "value1",
    key2: "value2"
};

var secondObject = extend({
    key3: "value3",
    key4: "value4"
}, firstObject );
1
  • This will also copy native properties. And how about properties that are Objects themselves?
    – KooiInc
    Commented Feb 20, 2012 at 15:06
2

If you wanted to grab only the properties that exist in the second object, you can use Object.keys to grab the properties of the first object, you can do two methods:

A.) map to assign the first object's properties to the second object using side effects:

var a = {a:100, b:9000, c:300};
var b = {b:-1};

Object.keys(a).map(function(key, index) {
    if (typeof b[key] !== 'undefined') {
        console.log(key);
        b[key] = a[key];    
    }
});

B.) or reduce to create a new object and assign it to the second object. Be aware that this method replaces other properties the second object might have before that which did not match the first object:

var a = {a:100, b:9000, c:300};
var b = {b:-1, d:-1}; // d will be gone

b = Object.keys(a).reduce(function(result, current) {
    if (typeof b[current] !== 'undefined') {
        result[current] = a[current];   
    }
    return result;
}, {});
2

For the record, this can now also be done with

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};
1

Object.assign or destructring may bite you seriously due to the fact that only top-level properties are copied as values.

All the nested properties will be copied as references and would keep the references to the original object's properties. If your object is flat, that is ok. But if not, these soultions are rarely applicable.

For simplest and effective one-liner I would recommend deepmerge package that is free from that drawback.

const newObject = deepmerge({}, oldObjectWithNestedProperties);

This would give you the completelly detached and independent newObject copy of your oldObjectWithNestedProperties.

0
0

I would rather use firstObject as prototype of secondObject, and add property descriptor:

var secondObject = Object.create(firstObject, {
      key3: {value: "value3", writable: true, configurable: true, enumerable: true},
      key4: {value: "value4", writable: true, configurable: true, enumerable: true}
      });

It's certainly not one-liner, but it gives you more control. If you are interested in property descriptors, I suggest to read this article: http://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 and MDN page https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

You can also just assign values and omit the descriptors and make it a bit shorter:

var secondObject = Object.create(firstObject, {
      key3: {value: "value3"}
      key4: {value: "value4"}
  });

Compatibility: ECMAScript 5, so IE9+

0
var firstObject = {
     key1: "value1",
     key2: "value2"
};

var secondObject = {
     key3: "value3",
     key4: "value4"
     copy: function(firstObject){
           this.key1 = firstObject.key1;
           this.key2 = firstObject.key2;
     }
 };

Using the follwing method will copy the properties

secondObject.copy(firstObject)

I am very new to javascript, but found this working. A little too long I guess, but it works.

Not the answer you're looking for? Browse other questions tagged or ask your own question.