I'll admit that maybe I'm the one with the massive mental block on this one. Maybe I'm the one who's fighting against the simple solution of the Monty Hall Problem. But every single time someone tries to explain to me why JS has no pass-by-reference, they either ignore the simple, tactical, repeatable examples I've already provided, or they say/show something that actually only furthers my case.
In my first example, I show a basic process by which we 1) initialize two variables, 2) pass those variables into new variables, 3) mutate the new variables, and 4) output the values of the original variables. In the example, the first original variable (the primitive value) is unchanged - because it's passed by value. The second original variable is changed - because it's passed by reference. It's already shown above, but here's a stripped down version of it:
It's obvious that something very different happens to the two original variables - mostImportantNumber and spanishNumbers.
We never performed any mutation directly on mostImportantNumber and, understandably, the value of mostImportantNumber remains constant. We never performed any mutation directly on spanishNumbers - yet the value of spanishNumbersis updated.
I don't know how I can make it any clearer than this. It's demonstrably, provably obvious that the newly-created variable germanNumbers maintains some kind of "link" back to its initializing variable spanishNumbers. It's demonstrable and provable because, when we update the members of germanNumbers, the change is reflected back on spanishNumbers.
As long as I've been programming, this "link" has been called a "reference". If you (or anyone else) wants to tell me that this "link" is not a "reference", then that's fine - but that leads me to your question:
Since passing a reference of the variable isn't even possible in JS, so why have a term for that anyway?
Because, in JS (and many other languages), the behavior of a passed primitive is demonstrably different than the behavior of a passed object.
It's really that simple. Why would we keep calling a "kick" a "throw" if it's demonstrably obvious that they're two different behaviors, and two different things are happening in those actions??? And why would we keep calling JS objects that have been passed "pass-by-value" when it's demonstrably obvious that they behave entirely differently from primitives that have been passed by value???
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 variablesletmostImportantNumber=3.14;letspanishNumbers={one:'uno',two:'dos',three:'tres'};// pass variables letanswerToEverything=mostImportantNumber;letgermanNumbers=spanishNumbers;// mutate variables answerToEverything=42;// This is an assignment, not a mutationgermanNumbers={one:'einz'}// This would be the equivalent operation for an object// output original variablesconsole.log(mostImportantNumber);// 3.14console.log(spanishNumbers);// { one: 'uno', two: 'dos', three: 'tres' } <-- Unchanged
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 defaultgermanNumbers.one='einz';// Since objects are mutable by default, this mutates 'germanNumbers'
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 variablesletmostImportantNumber=3.14;letspanishNumbers={one:'uno',two:'dos',three:'tres'};spanishNumbers=Object.freeze(spanishNumbers);// We freeze the object i.e. make it immutable like a primitive// pass variables letanswerToEverything=mostImportantNumber;letgermanNumbers=spanishNumbers;// mutate variables answerToEverything=42;germanNumbers.one='einz';// This mutation doesn't do anything, since the object is 'frozen' i.e. immutable// output original variablesconsole.log(mostImportantNumber);// 3.14console.log(spanishNumbers);// { one: 'uno', two: 'dos', three: 'tres' } <-- Unchanged
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
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I'll admit that maybe I'm the one with the massive mental block on this one. Maybe I'm the one who's fighting against the simple solution of the Monty Hall Problem. But every single time someone tries to explain to me why JS has no pass-by-reference, they either ignore the simple, tactical, repeatable examples I've already provided, or they say/show something that actually only furthers my case.
In my first example, I show a basic process by which we 1) initialize two variables, 2) pass those variables into new variables, 3) mutate the new variables, and 4) output the values of the original variables. In the example, the first original variable (the primitive value) is unchanged - because it's passed by value. The second original variable is changed - because it's passed by reference. It's already shown above, but here's a stripped down version of it:
It's obvious that something very different happens to the two original variables -
mostImportantNumber
andspanishNumbers
.We never performed any mutation directly on
mostImportantNumber
and, understandably, the value ofmostImportantNumber
remains constant. We never performed any mutation directly onspanishNumbers
- yet the value ofspanishNumbers
is updated.I don't know how I can make it any clearer than this. It's demonstrably, provably obvious that the newly-created variable
germanNumbers
maintains some kind of "link" back to its initializing variablespanishNumbers
. It's demonstrable and provable because, when we update the members ofgermanNumbers
, the change is reflected back onspanishNumbers
.As long as I've been programming, this "link" has been called a "reference". If you (or anyone else) wants to tell me that this "link" is not a "reference", then that's fine - but that leads me to your question:
Because, in JS (and many other languages), the behavior of a passed primitive is demonstrably different than the behavior of a passed object.
It's really that simple. Why would we keep calling a "kick" a "throw" if it's demonstrably obvious that they're two different behaviors, and two different things are happening in those actions??? And why would we keep calling JS objects that have been passed "pass-by-value" when it's demonstrably obvious that they behave entirely differently from primitives that have been passed by value???
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.
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.
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.
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!