8

I am still somewhat new to JavaScript, Node, etc. and come from a Groovy background (which has extremely similar syntax to JavaScript). In Groovy, I can easily do something like this:

def myMap1 = {};
def myMap2 = {};

myMap1["key1"] = "value1";
myMap1["key2"] = "value2";
myMap1["key3"] = "value3";

myMap1.each() { key, value =>
    myMap2[key] = value;
}

This would iterate through the existing map (myMap1) and copy the values for each key to the new map (myMap2), with the same key names. Easy as pie. However, JS has a concept of the prototype, which has been driving me crazy because you have to use hasOwnProperty, the index of the item sort of thing, etc and it results in a lot of code for something that's supposed to be really simple.

Looking at the MDN docs for Object(), it looks like JS has implemented something that allows a developer to access key/value pairs without having to deal with prototyping and all of that stuff, and you can just access the data in the object, and not properties of the object. I now have this:

var existingData = {"foo":"thing","bar":"otherThing","baz":"whatever"};
var update = {"foo":"newStuff","bar":"thisChanged","baz":"arghh"};

for (const [ key, value ] of Object.entries(update)) {
    console.log("Old value is " + existingData[key]);
    existingData[key] = value;
    console.log("Setting " + existingData[key] + " to " + value);
}

I would think this would work, but I get this in the console instead:

Old value is undefined
Setting thing to thing
Old value is undefined
Setting otherThing to otherThing
Old value is undefined
Setting whatever to whatever

It looks like existingData[key] does not reference the key in the key/value pair, but instead the value or something? How do I tell it, "for this key name in this second object, set this value?" I've been searching forever on Google and everything is either doing it the old way (with indexes) or is overly complicated for no particular reason. Any help would be greatly appreciated.

3
  • 4
    I can't reproduce you problem in the last code. I've changed it to a snippet so it runs in the browser and it shows different results than you are reporting. Commented Sep 16, 2018 at 18:44
  • I forgot to add "nodejs" to my tags and only briefly mentioned it in the question - my apologies - this is back end stuff only, so it may not work the same in a browser (although I would expect it to be the same). Commented Sep 16, 2018 at 19:27
  • It looks like you've found an answer that works for you, but as an FYI, I get precisely the same results in node as I do in the browser with the above code. If you're getting something different, there's a different issue. Commented Sep 16, 2018 at 21:12

4 Answers 4

10
for (let key in map1) {
    map2[key] = map1[key];
}

BTW why you dont use Object.assign(); ? (notice: it returns a new object)

let update = { "key1": "value1", "key2": "value2" };
let map2 = Object.assign({}, map1, update);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

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

3 Comments

Well, Object.assign(map2, map1) will mutate map2 and you don't need really to reassign it to map2
Object.assign will only shallow copy the object
It'll also only copy the top level of the object
7

Simply use Object.assign(map2, map1) to update map2 (copy key/value of map1 to map2)

Or you can use,

map2 = {...map2, ...map1} to build a new object and replace the map2 completely

To have a deep copy, instead of only first level you can use JSON.parse(JSON.stringify(map2)) instead of map2. If you think, its a large object and that impact performance, go for a nested implementation of copy recursively! ;-)

4 Comments

Using Object.assign and the es6 spread operators will only shallow copy the object
@matthew257 Hmm, and not deep copy, for nested objects/array it will be just the reference to the same object. But I think OP is bothered about only first level.
yep, always think it is best to play it safe though and just use JSON.parse(JSON.stringify(object));
Yup, I agree! instead of using map2 better to use JSON.parse(JSON.stringify(map2)) if need a deep copy.
2

You could just do this - looping through an array of the keys:

let myMap1 = {};
let myMap2 = {};

myMap1["key1"] = "value1";
myMap1["key2"] = "value2";
myMap1["key3"] = "value3";

// create an array of the keys in the object myMap1
let myMap1_keys = Object.keys(myMap1);

// loop through the array of object keys
for (let i = 0; i < myMap1_keys.length; i++) {
  myMap2[myMap1_keys[i]] = myMap1[myMap1_keys[i]];
}

I would advise not using a for..in loop i.e. as used in one of the other answers as these are slower than a native for loop (as used above). You can see some details regarding performance here: Comparing JavaScript loops performance (for, do while, for in)

If you are just interested in literally duplicating the object you can do that like so:

let myMap2 = JSON.parse(JSON.stringify(myMap1));

Anouther answer suggested using Object.assign() and anouther suggested using ES6 spread operators but these will 'shallow' copy the object which means the objects are using references to the original object and will only copy the top level of the object - the method above deep copies the object which I usually find is what is required for most use cases and will copy every level of the object.

6 Comments

Both of these appear to work: existingData = JSON.parse(JSON.stringify(update)); existingData = Object.assign({}, update, update); But now I get an error when I do a later .save(): TypeError: existingData.save is not a function
.save isn't a js function - what are you trying to do with the .save
Also, if you are happy that this answer answers the original question can you mark this answer as the answer - the tick sign - so it shows as resolved? on the .save issue, it might be better to open a new issue on StackOverFlow
This is in fact the answer, as it solved my original problem and dealt with the shallow copy issue as well, but to answer your question, the .save is being used with await for the purpose of mongoose/MongoDB update, like this: var savedOutput = await existingData.save() return savedOutput;
Great - you just need to click the tick sign next to my answer so the question is marked as resolved. Open a new question for the .save issue using the appropriate tags i.e. MongoDB and include a bit more code & background - I use MongoDB all the time so will be able to post on the new question if you drop a link to it here
|
0

You can iterate over keys. check is this helpful to you

var m1 = {};
let m2 = {};

m1["key1"] = "abc";
m1["key2"] = "def";
m1["key3"] = "ghi";

var m1_change_key = Object.keys(m1);

for (var i = 0; i < m1_change_key.length; i++) {
  m2[m1_change_key[i]] = m1[m1_change_key[i]];
 alert(m2[m1_change_key[i]])
}

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.