2 ms·
I 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
by Stratoscope 9y ago
I 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.
- Stratoscope 9y agoThat's true, "pass by reference" and "pass by value" are clearly defined terms in computer science. The problem is that legions of JavaScript programmers think that one or the other of those terms must apply to JavaScript, when neither one correctly describes the language's behavior. This leads to the widespread misconception that objects and primitives are handled in two different ways, one passed by reference and the other by value.
- pjmlp 9y agoI doubt there would be any serious compiler design lecture about implementing a JavaScript engine that would use anything other than "pass by value" to decribe how arguments are placed into the stack upon calling a function. The problem is trying to apply terms without understanding what they actually mean.
- Stratoscope 9y agoThis is exactly the problem I've been talking about. A compiler design lecture about implementing a JavaScript engine should not use the term "pass by value" to describe JavaScript's behavior. Most JavaScript engines to date have been written in C/C++. Function parameters are passed by value in these languages, unless you use a reference parameter in C++. This means that if the argument is a struct, the function receives a copy of the struct, not a reference to the original struct that was passed in. Consider this C code: typedef struct { int bar; } Foo; void fun( Foo boo ) { boo.bar = 43; } int main() { Foo foo; foo.bar = 42; printf( "Before call: %d\n", foo.bar ); fun( foo ); printf( "After call: %d\n", foo.bar ); return 0; } This will print: Before call: 42 After call: 42 fun() is passed a copy of the struct, so modifying the struct inside the function only affects its local copy. That's what "pass by value" means in C. Compare with the similar JavaScript: function fun( boo ) { boo.bar = 43; } function main() { let foo = { bar: 42 } console.log( "Before call:", foo.bar ); fun( foo ); console.log( "After call:", foo.bar ); } main(); This will log: Before call: 42 After call: 43 The function doesn't receive a copy of the object, it receives the object itself, under a new name. Using the term "pass by value" for JavaScript's behavior would only invite confusion.
- pjmlp 9y agoYou are doing pass by value on JavaScript example. For it to be pass by reference you need to change boo inside fun(), but you are changing a field of boo.bar using the boo address passed by value. When JavaScript starts having pass by reference, this code will hold true. Until then it won't, regardless how people re-invent CS concepts on HN. function fun( boo ) { boo = { bar: 42 } } function main() { let foo = null; console.log( "Before call:", foo); fun( foo ); console.log( "After call:", foo ); } main(); This will log: Before call: null After call: { bar: 42 }
- shkkmo 9y ago> I 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. The terms mean the same thing in every language. Some people (as shown in the article and this thread) don't understand what "pass-by-reference" means and incorrectly use it to apply to javascript. The pass-reference-by-value behavior is shared by a lot of languages, I'm not sure why you want to avoid comparison with them.
- Stratoscope 9y ago> The pass-reference-by-value behavior is shared by a lot of languages, I'm not sure why you want to avoid comparison with them. That's a fair point. I just think a lot of JavaScript programmers are confused about this, and end up thinking that primitives and objects are passed in two different ways. Even MDN makes this mistake: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid... My use of "things" and "names" is just an attempt to get away from this confusion.