how to pass by value in JavaScript

I have the following Situation:

let a=[{nome:"oi"},{nome:"xau"}]
let b=Object.assign([], a)

b[0].nome=5

console.log(b) //[{nome:5},{nome:xau}]
console.log(a) //[{nome:5},{nome:xau}]

A short time ago I asked here how to pass values without being by reference, they told me to use the Object.assing, but still it is not working, someone can help me as I would to change the b [0].name without changing the a?

Author: prmottajr, 2018-03-23

3 answers

The assign method makes a shallow copy, that is, copies the values of attributes that are of the object, but whatever is reference it copies the value of the reference. In your example a contains two references and so it is not working.

The suggestion I thought could help would be to use:

var b = JSON.parse(JSON.stringify(a))
 5
Author: prmottajr, 2018-03-23 16:26:42

One solution is to serialize the object and deserialize into a new one using JSON, like this:

let b=JSON.parse(JSON.stringify(a))

let a=[{nome:"oi"},{nome:"xau"}]
let b=JSON.parse(JSON.stringify(a))

b[0].nome=5

console.log(b[0]) //[{nome:5},{nome:xau}]
console.log(a[0]) //[{nome:5},{nome:xau}]

EDIT : @Everson pointed out about better explaining the reason for serializing/deserializing:

The serialize transforms object into stream, in the case of a JSON string, which will "break" the reference with the original object, and the deserialize transforms again into object, that reference, creating a new object

 3
Author: Ricardo Pontual, 2018-03-23 16:29:55

What you need is to make a Deep copy.

Unlike Shallow copy or shallow copy(explained in the answer of prmottajr), you need a copy that is created without any reference to the original data, which is applicable for object arrays for example.

Solution creating a method:

(method that will create a new object and copy the properties to that object)

var a=[{nome:"oi"},{nome:"xau"}]
var b = Clonar(a);

b[0].nome=5;

console.log(a, b);

function Clonar(source) {
    if (Object.prototype.toString.call(source) === '[object Array]') {
        var clone = [];
        for (var i=0; i<source.length; i++) {
            clone[i] = Clonar(source[i]);
        }
        return clone;
    } else if (typeof(source)=="object") {
        var clone = {};
        for (var prop in source) {
            if (source.hasOwnProperty(prop)) {
                clone[prop] = Clonar(source[prop]);
            }
        }
        return clone;
    } else {
        return source;
    }
}

Solution with jquery :

var a=[{nome:"oi"},{nome:"xau"}]
var b = jQuery.extend(true, {}, a);

b[0].nome=5;
console.log(a, b);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

As mentioned in other answers. Solution serializing and deserializing:

let a=[{nome:"oi"},{nome:"xau"}]
let b=JSON.parse(JSON.stringify(a))

b[0].nome=5

console.log(a,b)

Sources :

 1
Author: Caique Romero, 2018-03-23 16:56:26