5 ms·
On the "pass by value" vs. "pass by reference" controversy, I see two issues here: First, these terms have specific meaning in other languages such as C++, but
by Stratoscope 9y ago
On the "pass by value" vs. "pass by reference" controversy, I see two issues here:
First, these terms have specific meaning in other languages such as C++, but JavaScript's behavior does not match either of their definitions.
Second, there is a widespread myth that JavaScript passes primitive values and objects in two different ways. It doesn't. They work exactly the same, and making an artificial distinction between them is not useful.
I find it helpful to make up some new terminology, so my thinking isn't led astray by implied comparisons with other languages. I like to talk about names and things.
A name is a variable name or a parameter name.
A thing is any object or primitive value: anything that you can pass as a function argument or use on the right side of an assignment operator.
A name always refers to one thing. A thing can have multiple names.
When you pass an argument into a function, or when you use the assignment operator, you are giving a new name to an existing thing. If the name already referred to some other thing, that connection is lost. The name now refers to the new thing, and only to the new thing.
Everything works this way, primitives and objects alike.
The reason it's often claimed that objects are passed into a function by reference, while primitives are passed by value, is that we instinctively write different code for the two cases. That different code is what leads to the notion that objects and primitives are treated differently.
If you pass an object into a function and you want to add or change a property of that object, you'll naturally write:
function foo( obj ) {
obj.myprop = 42;
}
But if you know the function is going to receive a primitive value, you won't write this:
function foo( val ) {
val.myprop = 42;
}
If you do, you'll find out soon enough that it won't work. It will throw an exception in strict mode, or fail silently in non-strict mode.
Instead you may write:
function foo( val ) {
// Do stuff here with val
val = 42;
// Do stuff here with the *new* val, which isn't the old val
}
The reason the functions behave differently is not because JavaScript passes primitives and objects differently. It doesn't; they are all treated the same.
But primitives are immutable. They have no properties that we can change. We know that, or we find out if we try, so we simply don't write code that tries to change a property of a primitive value.
It isn't the JavaScript language that treats objects vs. primitives differently when passed into a function or when used in an assignment statement. We programmers do, by writing different code for the two.
(Edited for clarity)
- shkkmo 9y ago> The reason the functions behave differently is not because JavaScript passes primitives and objects differently. It doesn't; they are all treated the same. >The reason is that primitives are immutable This is incorrect. See: https://jsfiddle.net/t73ykuj0/ https://jsfiddle.net/t73ykuj0/ The reason is that javascript uses "pass-reference-by-value" not "pass-by-reference" edit: The immutability of primitives is why the "pass-reference-by-value" behavior of javascript works like "pass-by-value" for primitives (and for immutable objects).
- Stratoscope 9y agoI think we are saying the same thing. Your term "pass reference by value" is the same as what I called "give a new name to an existing thing". I simply like to avoid the terms "pass by reference" and "pass by value" to avoid comparison with other languages. But if you want to use "reference" and "value", then your term "pass a reference by value" is a good description of how it works - both for objects and primitives. Coincidentally, just before I saw your comment I changed what I said about "The reason is that primitives are immutable" to make it more clear. The real reason is that we instinctively write different code for the two. If a function parameter named 'val' is a primitive, we're not going to try to change a property on it. If we do, it won't work, because the primitive is immutable. (That's the point I was trying to get at with my original comment.) The same would be true, of course, with an immutable object. And when we pass an object into a function, we may reassign the name completely inside the function, as in the mutatePassByReference() function in your fiddle, but more likely we will write code that manipulates its properties, as in your mutatePassReferenceByValue(). So the immutability of primitives isn't the direct cause of what is sometimes thought of as different behavior for objects and primitives. It's an indirect cause, because it leads us to naturally write different code for the two. That's what I was really trying to get at (in my usual long-winded way): JavaScript doesn't treat objects and primitives differently, we programmers do.
- pjmlp 9y agoThere is no confusion between pass by reference" and "pass by value". They are clearly defined terms in Computer Science.