Arrays are passed by reference in javascript.
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.)
That means arrays are mutable and can be changed in called function.
No, that's not what it means. It means exactly what it says: that the reference within the caller's scope to the array is passed as an argument into the function, and not the value.
Whether or not the array is mutable or not has nothing to with pass-by-reference vs. pass-by-value. ECMAScript is not a purely functional language, most objects can be mutated. Number
s, Symbol
s, and String
s are an exception.
Why am I not able to Re-initialization an array in called function?
You are trying to modify the reference within the caller's scope. That only works with pass-by-reference. ECMAScript is not pass-by-reference, whoever told you that is simply wrong.
This is also true for python
Python behaves identically to ECMAScript in this regard, yes, it is also 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):
function isEcmascriptPassByValue(foo) {
foo.push('More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!');
foo = 'No, ECMAScript is pass-by-reference.';
return;
}
var bar = ['Yes, of course, ECMAScript *is* pass-by-value!'];
isEcmascriptPassByValue(bar);
console.log(bar);
// Yes, of course, ECMAScript *is* pass-by-value!,
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!
def is_python_pass_by_value(foo):
foo[0] = 'More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!'
foo = ['Python is not pass-by-reference.']
quux = ['Yes, of course, Python *is* pass-by-value!']
is_python_pass_by_value(quux)
print(quux[0])
# More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!
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.)
// In C#, struct defines a value type, class defines a reference type
struct MutableCell
{
public string value;
}
class Program
{
// the ref keyword means pass-by-reference, otherwise it's pass-by-value
// You must explicitly request pass-by-reference both at the definition and the call
static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
static void Main(string[] args)
{
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
// the first two are passed by value, the other two by reference
IsCSharpPassByValue(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
}
}