Whilst this is a great post and the overal information is correct, the pedantic semantic details are not. It all comes down to what it means to say something is "pass by x", and not what people who ask this question usually meant. I will explain why, but first
JavaScript is always pass by value
You're not the first one that tries to make a distinction between primitives and objects, and I understand why people do. However, there is none.
The term pass by reference and pass by valueonly applies to function calls and their arguments. Consider the following (JS syntax) code:
functionreference_assignment(myRefMaybe){myRefMaybe={key:42}}varprimitiveValue=1varsomeObject={is:'changed?'}reference_assignment(primitiveValue)primitiveValue// => 1reference_assignment(someObject)// => { is: 'changed?' }
The fact is that someObject has not been changed, because it was not a reference to someObject's content that has been passed. A language that does support pass by reference is PHP, but it requires special syntax to change from the default of passing by value:
I tried to keep the same sort of semantic as the JS code.
As you can see, the PHP example actually changes the value the input argument refers to.
What's wrong with call-by-value?
The term call-by-value is problematic. In JavaScript the value that is passed is a reference. That means that, indeed, that the reference to the boxed primitive is copied, and therefore changing a primitive inside a function doesn't affect the primitive on the outside. That also means that, indeed, the reference to a reference type, such as an array or object, is copied and passed as the value. This results in the exact behaviour that is described.
The lesser used and known term that was coined is Call by sharing which applies to Ruby, JavaScript, Python, Java and so forth. It implies that all values are object, all values are boxed, and they copy a reference when they pass it as value.
In the first example it outputs [1], because the push method modifies the object on which it is called. This propagates because the list argument still refers to the original object first (its reference was copied and passed as a value).
In the second example it outputs [] because the re-assignment doesn't propagate to the caller. In the end it is not re-assigning the original reference but only a copy.
In short: It's always pass by value, but the value of the variable is a reference. All primitive-methods return a new value and thus one can not modify it, all objects and arrays can have methods that modified their value, and thus one can modify it.
P.S. C actually is also always pass by value / call by value, but it allows you to pass a pointer which can simulate pass by reference:
voidmodifyParameters(intvalue,int*pointerA,int*pointerB){// passed by value: only the local parameter is modifiedvalue=42;// passed by value or "reference", check call site to determine which*pointerA=42;// passed by value or "reference", check call site to determine which*pointerB=42;}intmain(){intfirst=1;intsecond=2;intrandom=100;int*third=&random;// "first" is passed by value, which is the default// "second" is passed by reference by creating a pointer,// the pointer is passed by value, but it is followed when// using *pointerA, and thus this is like passing a reference.// "third" is passed by value. However, it's a pointer and that pointer// is followed when using *pointerB, and thus this is like// passing a reference.modifyParameters(first,&second,third);// "first" is still 1// "second" is now 42// "random" is now 42// "third" is still a pointer to "random" (unchanged)return0;}
Yeah I do apologize for potentially spreading misinformation. I was just recapping things I learned in an Advanced Javascript course.
Link me to your post when you make it, and I'll add it at the bottom of this one as a "However, this is more nuanced than it seems on the surface, for a deeper dive check out this article."
If you try to look this up, most resources will actually mention it incorrectly and even hostile toxic discussion against people who say exactly what I say :(. I only know what I know because I spend quite some time in this implementation in V8 and MRI ruby (and because I had some of this in university).
It also doesn't help that it's really mostly semantics and pedantic, but nomenclature can definitely confusing. I hope you can turn my explanation in a few sentences for the #beginners ❤
This exactly. Almost no resource explains this correctly and I think that this is one of the harder things to explain to beginners, but also one of the most important. Obviously, someone who had some C/C++ education would be a bit better at understanding the reasons why this happens, but even those lessons are usually not very good at explaining the differences in detail.
Your explanation on the other hand is pretty good. And good job! :)
That said, I completely understand where Brian is coming from. It's moreso the lack of writing than that it's super hard. I think Brian did a stellar job giving us the difference of passing an object/array vs primitive, in the practical sense, which is in the end the only thing the beginner will really use.
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.
Whilst this is a great post and the overal information is correct, the pedantic semantic details are not. It all comes down to what it means to say something is "pass by x", and not what people who ask this question usually meant. I will explain why, but first
JavaScript is always pass by value
You're not the first one that tries to make a distinction between primitives and objects, and I understand why people do. However, there is none.
The term
pass by reference
andpass by value
only applies to function calls and their arguments. Consider the following (JS syntax) code:The fact is that
someObject
has not been changed, because it was not areference
tosomeObject
's content that has been passed. A language that does supportpass by reference
is PHP, but it requires special syntax to change from the default of passing by value:I tried to keep the same sort of semantic as the JS code.
As you can see, the PHP example actually changes the value the input argument refers to.
What's wrong with call-by-value?
The term
call-by-value
is problematic. In JavaScript the value that is passed is a reference. That means that, indeed, that the reference to the boxed primitive is copied, and therefore changing a primitive inside a function doesn't affect the primitive on the outside. That also means that, indeed, the reference to a reference type, such as an array or object, is copied and passed as the value. This results in the exact behaviour that is described.The lesser used and known term that was coined is Call by sharing which applies to Ruby, JavaScript, Python, Java and so forth. It implies that all values are object, all values are boxed, and they copy a reference when they pass it as value.
Here is another example to demonstrate this:
In the first example it outputs
[1]
, because thepush
method modifies the object on which it is called. This propagates because thelist
argument still refers to the original objectfirst
(its reference was copied and passed as a value).In the second example it outputs
[]
because the re-assignment doesn't propagate to the caller. In the end it is not re-assigning the original reference but only a copy.In short: It's always pass by value, but the value of the variable is a reference. All primitive-methods return a new value and thus one can not modify it, all objects and arrays can have methods that modified their value, and thus one can modify it.
P.S. C actually is also always pass by value / call by value, but it allows you to pass a pointer which can simulate pass by reference:
Thank you! I see the misconception about pass by reference / value a lot.
This comment should probably be it's own blog post.
I will!
Yeah I do apologize for potentially spreading misinformation. I was just recapping things I learned in an Advanced Javascript course.
Link me to your post when you make it, and I'll add it at the bottom of this one as a "However, this is more nuanced than it seems on the surface, for a deeper dive check out this article."
Don't worry! Keep recapping. Like I said, it holds value :)
I'll reply here with the link once it's up!
JavaScript, Ruby and C are not call by reference
Derk-Jan Karrenbeld ・ Jun 27 ・ 9 min read
Wow, the resources I used to learn Javascript never mentioned this at all, thanks for sharing! Very illuminating.
If you try to look this up, most resources will actually mention it incorrectly and even hostile toxic discussion against people who say exactly what I say :(. I only know what I know because I spend quite some time in this implementation in V8 and MRI ruby (and because I had some of this in university).
It also doesn't help that it's really mostly semantics and pedantic, but nomenclature can definitely confusing. I hope you can turn my explanation in a few sentences for the #beginners ❤
This exactly. Almost no resource explains this correctly and I think that this is one of the harder things to explain to beginners, but also one of the most important. Obviously, someone who had some C/C++ education would be a bit better at understanding the reasons why this happens, but even those lessons are usually not very good at explaining the differences in detail.
Your explanation on the other hand is pretty good. And good job! :)
I guess I'll write an article.
That said, I completely understand where Brian is coming from. It's moreso the lack of writing than that it's super hard. I think Brian did a stellar job giving us the difference of passing an object/array vs primitive, in the practical sense, which is in the end the only thing the beginner will really use.