According to this question, if I pass a global variable as an argument to a function, that global bees a local copy.
If that is the case, why does this jfiddle behave the way it does? Shouldn't the alert show dog, cat
and not just cat
?
I even went one further step than the example and specifically copied the global variable into a local variable, but the result is the same. I'd really like to be able to shift()
the local while keeping the global intact.
According to this question, if I pass a global variable as an argument to a function, that global bees a local copy.
If that is the case, why does this jfiddle behave the way it does? Shouldn't the alert show dog, cat
and not just cat
?
I even went one further step than the example and specifically copied the global variable into a local variable, but the result is the same. I'd really like to be able to shift()
the local while keeping the global intact.
- Arrays and Objects are exceptions. They share same reference. You need to learn about those :) – Vigneswaran Marimuthu Commented Apr 21, 2015 at 5:26
-
2
It doesn’t make a copy. It’s an assignment like any other variable. See stackoverflow./a/5314911/707111. You can copy arrays using
.slice()
. – Ry- ♦ Commented Apr 21, 2015 at 5:26 - Dupe - stackoverflow./questions/13104494/… – adeneo Commented Apr 21, 2015 at 5:28
- 4 primitives are passed by value, object are passed by reference – webduvet Commented Apr 21, 2015 at 5:29
- 2 Not by reference, by value, containing a reference – adeneo Commented Apr 21, 2015 at 5:29
2 Answers
Reset to default 6JavaScript only has pass-by-value. I just wanted to make it clear from the beginning.
To keep things simple, the code below illustrates the difference between pass-by-value and pass-by-reference.
Pass-by-value
function change (x) { x = 7; }
var x = 1;
change(x);
console.log(x); // 1
Pass-by-reference (not available in JavaScript)
function change (x) { x = 7; }
var x = 1;
change(x);
console.log(x); // 7
Now, you need to understand that some types are allocated on the heap, while others are allocated on the stack. So what does that mean?
Well, let's suppose you have a variable.
var x = 5;
Here the value lives on the stack. Which means, if I do
var y = x;
I will have two variables on the stack, both with their own copy of 5
. Simple types are always allocated on the stack.
Objects, on the other hand, live on the heap. When I do,
var o1 = {x: 5};
the object will be allocated on the heap, but the value within o1
variable, which is a reference to the object in the heap (let's call #ref1
the value within o1
variable), will be allocated on the stack. Which means, if I do
var o2 = o1;
I will have two variables on the stack, both with their own copy of #ref1
, but only one object allocated on the heap.
Now, you can use the reference to access object's members, and because both o1
and o2
contain a reference to the same object, they will be able to locate the object in the heap an change it's x
value.
If, however, I do the following
o2 = {x: 7};
this will change the value stored on the stack for the variable o2
(will call the new value #ref2
). Now, there are two objects on the heap and two references stored on the stack.
Finally, let's talk about your problem:
// The array (which is an object) is allocated on the heap
// {animals} variable will contain a reference to that object (#ref1)
var animals = ["dog", "cat"];
// Pass-by-value
pushSearchList(animals);
// Local variable {passedAnimals} will contain a copy of #ref1,
// but both {passedAnimals} and {animals} can modify the same object
function pushSearchList(passedAnimals){
var localAnimals = passedAnimals;
localAnimals.shift();
alert(animals);
}
Now, what if you want your own copy of the array object? Just clone the array using:
// {arr} will receive reference to a new array allocated on the heap (#ref2)
var arr = passedAnimals.slice(0);
Considering this code:
var animals = ["dog", "cat"];
pushSearchList(animals);
function pushSearchList(passedAnimals){
var localAnimals = passedAnimals;
localAnimals.shift();
alert(animals);
}
animals
is NOT copied to the function. It is passed by reference. Anything you do to the passedAnimals
ARRAY will affect animals
as well. If you SET the variale passedAnimals
to something else, like a copy of itself (ie. passedAnimals.slice()
), then changes to the new array will no longer affect the source. Because array objects can be changed, they are mutable (liable to change).
In contrast, strings on the other hand (though they can look like an array of characters) are immutable (cannot change). If you pass them to a parameter, a copy will be made.
More on passing by value or reference: http://snook.ca/archives/javascript/javascript_pass