DEV Community

Discussion on: A "Gotcha" of JavaScript's Pass-by-Reference

Collapse
 
unchar1 profile image
Askara Novaru • Edited

Because, in JS (and many other languages), the behavior of a passed primitive is demonstrably different than the behavior of a passed object.

Actually there's no practical difference between how JS passes a primitive value or an object. I'm sorry if I came off wrong. I was just pointing out where a lot of people who were arguing about it where coming from. As for the example you provided.

// initialize variables
let mostImportantNumber = 3.14;
let spanishNumbers = { one: 'uno', two: 'dos', three: 'tres' };
// pass variables 
let answerToEverything = mostImportantNumber;
let germanNumbers = spanishNumbers;
// mutate variables 
answerToEverything = 42; // This is an assignment, not a mutation
germanNumbers = { one: 'einz' } // This would be the equivalent operation for an object
// output original variables
console.log(mostImportantNumber);  // 3.14
console.log(spanishNumbers); // { one: 'uno', two: 'dos', three: 'tres' } <-- Unchanged
Enter fullscreen mode Exit fullscreen mode

The JS runtime has no reason to treat a primitive assignment differently to an object assignment. In fact, you can even try to mutate a primitive just like an object, and JS will allow you to do that as well. It just throws away any mutations you make, which is why it appears that you are operating on another copy of the primitive. But in reality both variables point to the same primitive as well.

answerToEverything.one = 42; // Perfectly valid, it just doesn't mutate 'answerToEverything', since primitives are immutable by default
germanNumbers.one = 'einz'; // Since objects are mutable by default, this mutates 'germanNumbers'
Enter fullscreen mode Exit fullscreen mode

In fact, if you freeze the object, you can make an object immutable as well, and essentially get the same behavior between objects and primitives, which demonstrates that you don't need to copy anything to make an object behave like a primitive.

// initialize variables
let mostImportantNumber = 3.14;
let spanishNumbers = { one: 'uno', two: 'dos', three: 'tres' };
spanishNumbers = Object.freeze(spanishNumbers); // We freeze the object i.e. make it immutable like a primitive
// pass variables 
let answerToEverything = mostImportantNumber;
let germanNumbers = spanishNumbers;
// mutate variables 
answerToEverything = 42;
germanNumbers.one = 'einz'; // This mutation doesn't do anything, since the object is 'frozen' i.e. immutable
// output original variables
console.log(mostImportantNumber);  // 3.14
console.log(spanishNumbers); // { one: 'uno', two: 'dos', three: 'tres' } <-- Unchanged
Enter fullscreen mode Exit fullscreen mode

I suppose you could say that primitives are like objects that are just frozen by default. While this is technically not true, unless you attempt any operation specific to a primitive (such as addition,subtraction,etc), for the JS Runtime, they are treated exactly in the same way (such as when assigning them to variables or passing them to functions)

I hope that helps clear things up a bit!

Some comments have been hidden by the post's author - find out more