Object are passed with their reference in javascript. Meaning change in that object from any where should be reflected. In this case, the expected output was {} for console.log(a)
function change(a,b) {
a.x = 'added';
a = b;//assigning a as {} to b
}
a={}
b={}
change(a,b);
console.log(a); //expected {} but output {x:'added'}
console.log(b)
What is happening here? It should not be because of functional scope as far as I know. Thank you
This should help to solve your problem:
The variable 'a' in the context of your function is not the same as the 'a' variable outside the function. This code is semantically equivalent to yours:
It's obvious in this case that the 'foo' variable only exists inside the function, and doing
foo = bar
doesn't changea
as the reference is passed by value.If you added another line you can get a clearer picture of what is happening:
When you're doing
a = b
you're assigning the local variablea
to the reference thatb
is holding.No, they aren't. ECMAScript/JavaScript is strictly pass-by-value. (More precisely, call-by-sharing, which is a special case of pass-by-value.)
This is just normal pass-by-value.
Your confusion stems from the fact that you erroneously believe ECMAScript/JavaScript is pass-by-reference, when in fact it is not.
ECMAScript uses pass-by-value, or more precisely, a special case of pass-by-value where the value being passed is always a pointer. This special case is also sometimes known as call-by-sharing, call-by-object-sharing or call-by-object.
It's the same convention that is used by Java (for objects), C# (by default for reference types), Smalltalk, Python, Ruby and more or less every object-oriented language ever created.
Note: some types (e.g.
Number
s) are actually passed directly by value and not with an intermediary pointer. However, since those are immutable, there is no observable behavioral difference between pass-by-value and call-by-object-sharing in this case, so you can greatly simplify your mental model by simply treating everything as call-by-object-sharing. Just interpret these special cases as internal compiler optimizations that you don't need to worry about.Here's a simple example you can run to determine the argument passing convention of ECMAScript (or any other language, after you translate it):
If you are familiar with C#, it is a very good way to understand the differences between pass-by-value and pass-by-reference for value types and reference types, because C# supports all 4 combinations: pass-by-value for value types ("traditional pass-by-value"), pass-by-value for reference types (call-by-sharing, call-by-object, call-by-object-sharing as in ECMAScript), pass-by-reference for reference types, and pass-by-reference for value types.
(Actually, even if you don't know C#, this isn't too hard to follow.)
You are right that objects are passed by reference and any change made to the object in the function will be reflected everywhere. This is precisely why adding the
x
property in the function modified the object outside of it.What you are missing is that the line
a = b;
does not modify the object, it modifies the reference to the object. You can pass both of the objects in another container object / array if you need to set the reference:Okay, so you've figured out that JavaScript objects have reference semantics, so modifying a referent has an effect on the same object in the original scope.
What you also need to realise is that
=
is not part of these rules; not only does it perform assignment, but it will also rebind the reference to a new object.Under the hood, so to speak, that's basically how your original references were formed.