13

I have this structure:

var a = [];
a.push({"level": 1, "column": 4, "parent": "none", "title": "Node 0", "content": "Parintele suprem", "show": "1"});
var b = a;

a.push({"level": 1, "column": 5, "parent": "none", "title": "Node 1", "content": "Parintele suprem", "show": "1"});

console.log(b);

Now the problem is that b has the exact content as a (the content after the second push). This suggest (correct me if I'm wrong) that when I said b = a I actually gave b same reference as a, so whatever I do in a I have in b. The thing is that I need to pass the value. So I have the previews a, value in b.

Edit to make the question more clear: How do I pass the value instead of the reference?

Cœur
  • 37,241
  • 25
  • 195
  • 267
zozo
  • 8,230
  • 19
  • 79
  • 134
  • "The thing is that I need to pass the value. So I have the previews a value in b.". Or to spell it like a question: "How do I pass the value instead of the referance?". – zozo Feb 08 '12 at 09:27

5 Answers5

19

I think you can use this to copy the value instead of the reference:

var b = a.slice(0);  

EDIT
As the comments have mentioned and it's also mentioned here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/slice

slice does not alter the original array, but returns a new "one level deep" copy that contains copies of the elements sliced from the original array. Elements of the original array are copied into the new array as follows:

  • For object references (and not the actual object), slice copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays.

  • For strings and numbers (not String and Number objects), slice copies strings and numbers into the new array. Changes to the string or number in one array does not affect the other array.

If a new element is added to either array, the other array is not affected.

Niklas
  • 13,005
  • 23
  • 79
  • 119
  • 1
    Works like a dream :). I can't accept the answer yet, but I will in 7 minutes (when stack will allow me). – zozo Feb 08 '12 at 09:30
  • Seems so. I'll make a quick test after I finish current task :). Also since there are more than 1 valid answers I'll make a post answering witch would be faster... from my quick test seems like slice. But since I don't have a logical explanation I can't be sure. – zozo Feb 08 '12 at 09:34
  • 1
    @zozo. Note that it will work only for arrays and not for objects. see my answer. – gdoron Feb 08 '12 at 09:35
  • Correct... but I can't use prototype and unless clone is faster I don't have any use to make a clone function since the slice fits my current needs. +1 tho. – zozo Feb 08 '12 at 09:40
  • 3
    +1 Note that the behavior of `slice` if you give it **no** arguments [is not defined in the spec](http://es5.github.com/#x15.4.4.10), and so `var b = a.slice();` is relying on unspecified, undocumented behavior. To avoid relying on that, just pass `0`: `var b = a.slice(0);` – T.J. Crowder Feb 08 '12 at 09:44
  • @RobAgar: Correct, only *array index* properties are copied; [see the spec](http://es5.github.com/#x15.4.4.10). If the array instance has other properties, they will not be copied. – T.J. Crowder Feb 08 '12 at 09:46
7

you can implement a clone method as follow:

function clone(source) {
    var result = source, i, len;
    if (!source
        || source instanceof Number
        || source instanceof String
        || source instanceof Boolean) {
        return result;
    } else if (Object.prototype.toString.call(source).slice(8,-1) === 'Array') {
        result = [];
        var resultLen = 0;
        for (i = 0, len = source.length; i < len; i++) {
            result[resultLen++] = clone(source[i]);
        }
    } else if (typeof source == 'object') {
        result = {};
        for (i in source) {
            if (source.hasOwnProperty(i)) {
                result[i] = clone(source[i]);
            }
        }
    }
    return result;
};

then:

var b = clone(a);

if you are sure that a is Array, only use Niklas's:

var b = a.slice();

ps: my english is poor:)

subei
  • 71
  • 3
4

The easiest way i could find is to just make a json string and then parse the data.

var assiging_variable = JSON.parse(JSON.stringify(source_array));

This also works if the source array is a multidimensional array, the array.slice(0) method does not work for multidimensional array.

Mirza Prangon
  • 115
  • 12
  • It is indeed the easiest. Although not the most optimal ;). Still +1. It is rather interesting no1 mentioned this before :)). – zozo Aug 21 '20 at 15:01
  • I'm sad that is the only solution which worked for me... I was iterating from array A and filtering , removing and adding objects and properties to array B and this is the only thing which worked for me . I'm coming from Python and I don't use to all of the NodeJS\JavaScript unique thinking. – Gil Allen Dec 28 '20 at 08:58
  • let obj_A = Object.assign({}, obj_B ); – Gil Allen Dec 28 '20 at 09:26
3

Yes, that's the way reference assignment works in javascript. You want to clone the object to make a copy, which is unfortunately more involved than it should be. Frameworks like MooTools provide the simplest solution, or you can roll your own clone function.

Rob Agar
  • 12,337
  • 5
  • 48
  • 63
0

I found a nicer way by using "Object.assign({}, source_object )":

let source_obj  = {val1:"A",val2:"B"};
let copy_obj = Object.assign({}, source_obj);
Gil Allen
  • 1,169
  • 14
  • 24