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

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.