8

The following in a Javascript console:

var a = {'foo': []}; var b = {}; for (var key in a) { b[key] = a[key]; } a['foo'].push(1); console.log(b); 

Yields:

Object foo=[1]

I want to make a copy by value in b of each array for each key in a. Is there an easier way?

3
  • How do you get a "javascript console"? Commented Oct 23, 2009 at 18:44
  • Oscar- using Firebug inside Firefox, or Safari's Web Inspector. Commented Oct 23, 2009 at 18:52
  • @Oscar: You need FireBug for console.log function to work. Commented Oct 23, 2009 at 18:52

4 Answers 4

4

You could make a "clone" function that creates a new object, based on the original object constructor, and then clone that original object properties also if they are objects:

function clone(obj){ if(typeof(obj) != 'object' && obj != null) return obj; // return the value itself if isn't an object // or null, since typeof null == 'object'; var temp = new obj.constructor(); for(var key in obj) temp[key] = clone(obj[key]); return temp; } var a = {'foo': []}; var b = clone(a); a['foo'].push(1); console.log(b); // Object foo=[0] 
Sign up to request clarification or add additional context in comments.

5 Comments

I ran across this problem before, and this is exactly how I solved it. +1
Prototyping breaks this. Simply Object.prototype.foo = function () {}; will create infinite recursion.
@Jonathan: added an if statement to stop recursion.
Same problem here CMS: obj.constructor() is going to die on constructor functions (temp will be undefined), and potentially clobber globals.
@Crescent: Exactly, the same problem!, added the new operator while I think on something better...
3

This is called Deep Copy. You can find examples in:

Comments

0

Easier way:

var a = {'foo': []}; var b = a; a['foo'].push(1); console.log(b); 

Output is the same.

Edit:

var a = {'foo': []}; var b = {}; for (var key in a) { if (a.hasOwnProperty(key)) { b[key] = []; for (var i = 0; i < a[key].length; i += 1) { b[key][i] = a[key][i]; } } } a['foo'].push(1); console.log(b); 

3 Comments

Anatoliy: I don't want b to simply be a reference to a; I want b to be a unique copy by value of the arrays stored in a so that when I push to a's arrays it does not affect b.
Fixed. Currently output is object with empty array.
You can simplify all of that deep-copy stuff with a[key].slice(0).
0

As this will add support for deep-copying arrays in your code:

var a = {'foo': []}; var b = {}; for (var key in a) { if (Object.prototype.toString.call(b[key]) === "[object Array]") { b[key] = a[key].slice(0); } else { b[key] = a[key]; } } a['foo'].push(1); console.log(b); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.