Is JS pass-by-reference or by value ?

TL;DR

JS use pass by value for primitive and by reference for object and array (simplification inside).

So how to :

  • Copy a (not nested) array :
var my_copy = my_array.slice(0); // ATTENTION : works for not nested array !
  • Cloning a (not nested) object : (look here for source + polyfill for obj.assign())
var my_obj = { a: 1 }; // If you don’t have nested object !
var my_copy = Object.assign({}, my_obj);// ATTENTION : works for not nested object !
console.log(my_copy);  // {a: 1} 
  • And for deep cloning my nested object or array :

… Sadly, there is currently no method in vanilla JS, I suggest you use external library✶ lodash cloneDeep() method to fill that need

✶: Ho, yes : avoid jQuery for such simple task

The underlying explanation

In fact javascript is not a pure call-by-value nor a pure call-by-reference language : it’s call-by-sharing, here is an example/consequence of this :

function changeStuff(a, b, c) {
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"}; // → this one will be surprising :)
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);       // 10
console.log(obj1.item); // changed
console.log(obj2.item); // unchanged

The output will be :

10
changed
unchanged

Because :

  • num is a primitive so it’s value is passed by copy, and leave only inside the function scope.
  • obj1 is an object so it’s reference is passed, and modification leave outside the function scope.
  • when you assign obj2 a value of {item: “changed”} you are changing the reference to a new object (which immediately goes out of scope when the function exits).

More ressources on this on StackOverFlow and here