3 ms·
That'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
by Stratoscope 9y ago
That'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 }
- zzzcpan 9y agoPlacing arguments into the stack is an implementation detail and it can be done either way. For example, we can hold a reference to a struct representing a primitive value and place it onto the stack. If we let our callee modify this struct we get a behavior you understand as pass-by-reference. Otherwise we can copy this struct into a new struct on write and replace the reference on the stack. This way we are passing references, but implementing pass-by-value behavior. We can do the same for non-primitive data structures, etc. So these things are about behavior, not implementation. And Javascript does have a behavior where it passes certain things as references implicitly stored in variables. It's in no way pass by value.
- pjmlp 9y agoWhen JavaScript starts having pass by reference, this code will hold true. 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 }
- zzzcpan 9y agoI don't know why it's so hard to understand. It's not the essence of passing by reference, you are mixing implementation details with semantics. If you can modify something that you didn't __explicitly__ use as a reference, you have an implicit pass by reference behavior. It doesn't matter if you can't modify the root reference itself of a nested structure, but only the children. You still can modify something that you didn't explicitly specify, so it is still pass by reference. And by the way, CS has no precise terminology about this, CS prefers to neglect usability side of programming languages altogether.
- shkkmo 9y ago> It's not the essence of passing by reference, you are mixing implementation details with semantics. > And by the way, CS has no precise terminology about this, That is not correct. You are the one mixing up terms. Pass-by-reference and Pass-by-value have specific meanings. There are two acceptable terms for how Javascript passes variables, those are "pass-by-sharing" or "pass-reference-by-value" https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sh...