to my understanding, both array and objects are Pass By Reference based on the memory address, so if I create another variable and point to the array/object, and mutate any of the values, another value should also be changed.
However, I don't quite understand how it works here. I am pointing to array1 and modifying array1 to empty, why the value at anotherArray does not change?
var array1 = [1,2,3,4,5,6,7]; // Created array
var anotherArray = array1; // Referenced array1 by another variable
array1 = []; // Empty the array
console.log(anotherArray); // Output [1,2,3,4,5,6,7]
I can understand the below example why the anotherArray becomes [] empty because it is passed by reference, but why the anotherArray still output [1,2,3,4,5,6,7] for the above?
var array1 = [1,2,3,4,5,6,7]; // Created array
var anotherArray = array1; // Referenced array1 by another variable
array1.length = 0; // Empty the array by setting length to 0
console.log(anotherArray); // Output []
Thank you.
CodePudding user response:
Assigning to a variable never changes the object that the variable previously had as value.
Objects -- such as arrays -- only change when you mutate them, either through calling a method that does this, or by setting a property.
Here is a visualisation of your first script:
var array1 = [1,2,3,4,5,6,7]
results in this:
array1
↓
┌──────┬───┬───┬───┬───┬───┬───┬───┐
│length│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │
├──────┼───┼───┼───┼───┼───┼───┼───┤
│ 7 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
└──────┴───┴───┴───┴───┴───┴───┴───┘
After var anotherArray = array1
we have this:
array1
↓
┌──────┬───┬───┬───┬───┬───┬───┬───┐
│length│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │
├──────┼───┼───┼───┼───┼───┼───┼───┤
│ 7 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
└──────┴───┴───┴───┴───┴───┴───┴───┘
↑
anotherArray
Then array1 = []
will create a new array: so there are now two arrays. It also makes array1
a reference for the newly created array:
array1
↓
┌──────┐
│length│
├──────┤
│ 0 │
└──────┘
┌──────┬───┬───┬───┬───┬───┬───┬───┐
│length│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │
├──────┼───┼───┼───┼───┼───┼───┼───┤
│ 7 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
└──────┴───┴───┴───┴───┴───┴───┴───┘
↑
anotherArray
In the second script the assignment to the length
property (actually a setter) will mutate the array. There is no new array created, and the values 1,2,3,4,5,6,7 are lost:
array1
↓
┌──────┐
│length│
├──────┤
│ 0 │
└──────┘
↑
anotherArray
CodePudding user response:
For your first example, you are actually making a reassignment to array1 as an empty array (and now they are pointing to 2 different arrays in the memory), hence the anotherArray remains unchanged.
var array1 = [1,2,3,4,5,6,7]; // Created array
var anotherArray = array1; // Referenced array1 by another variable
array1 = []; // Empty the array
console.log(anotherArray); // Output [1,2,3,4,5,6,7]
In this case, you are actually modifying the array by assigning it's length to 0. since array1 refers to it, it impacts on him as well since they are referring the same array in the memory.
var array1 = [1,2,3,4,5,6,7]; // Created array
var anotherArray = array1; // Referenced array1 by another variable
array1.length = 0; // Empty the array by setting length to 0
console.log(anotherArray); // Output []
CodePudding user response:
The line
array1 = [];
does not modify the array object previously assigned to array1
. It assigns a new (empty) array to the variable; it's not like invoking an operation on the object assigned to array1
.
To explain it in other words, assume array1
was the only variable referring the previously assigned array object ([1,2,3,4,5,6,7]
). Upon execution of that line (which is a statement, btw) you got lost of the previously assigned array; and it would be garbage collected some time later. This is all because the assignment operator is used here and they way its operational semantics is defined in JavaScript.
What is more, your are misusing the concept of pass by reference here (a.k.a. call by reference); which is a concept that relates to how values are passed to arguments of functions calls (or sub routines/procedures, if you prefer speaking of sub routines/procedures rather than functions).
CodePudding user response:
In the first instance you're not actually updating the object that is referenced by array1.
You're replacing the value under the variable name array1
. anotherArray
is pointing to the value in memory that was the previous value held in array1
.
In the second example you're actually updating the underlying value that array1
and anotherArray
are both pointing to
CodePudding user response:
In the assignment operator, a = x
, the right-hand side is evaluated as an expression (x
) and the resulting value is assigned to a
.
This implies that a
never “references” x
.
Thus both a = b
and a = []
result in a
being re-assigned. It is irrelevant if the right-hand side is a variable (that is evaluated) or an empty array literal:
var b = [1,2,3]
var a = b
// ^— a is assigned the result of evaluating b
// after this assignment a and b will then
// “refer to”, as in will evaluate to, the same object
// b -> [1,2,3]
// a -> [1,2,3]
a.pop()
// ^— modify array object
// since a and b “refer to” the same object..
// b -> [1,2]
// a -> [1,2]
var a = []
// ^— a is assigned the result of evaluating []
// now a and b “refer to” different array objects
// b -> [1,2]
// a -> []
Calling functions works the exact same way as assignments and there is no “call by reference” in Javascript. The values that result from the evaluation of expressions are supplied as arguments. (Javascript has Call by (Object) Sharing semantics.)
tldr: there is no need to talk about “references” in Javascript here, as they add needless confusion and are not even defined (in this manner) in the specification!