JavaScript by reference vs. by value
Solution 1
My understanding is that this is actually very simple:
- Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
- Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
- However, changing a property of an object referenced by a variable does change the underlying object.
So, to work through some of your examples:
function f(a,b,c) {
// Argument a is re-assigned to a new value.
// The object or primitive referenced by the original a is unchanged.
a = 3;
// Calling b.push changes its properties - it adds
// a new property b[b.length] with the value "foo".
// So the object referenced by b has been changed.
b.push("foo");
// The "first" property of argument c has been changed.
// So the object referenced by c has been changed (unless c is a primitive)
c.first = false;
}
var x = 4;
var y = ["eeny", "miny", "mo"];
var z = {first: true};
f(x,y,z);
console.log(x, y, z.first); // 4, ["eeny", "miny", "mo", "foo"], false
Example 2:
var a = ["1", "2", {foo:"bar"}];
var b = a[1]; // b is now "2";
var c = a[2]; // c now references {foo:"bar"}
a[1] = "4"; // a is now ["1", "4", {foo:"bar"}]; b still has the value
// it had at the time of assignment
a[2] = "5"; // a is now ["1", "4", "5"]; c still has the value
// it had at the time of assignment, i.e. a reference to
// the object {foo:"bar"}
console.log(b, c.foo); // "2" "bar"
Solution 2
Javascript always passes by value. However, if you pass an object to a function, the "value" is really a reference to that object, so the function can modify that object's properties but not cause the variable outside the function to point to some other object.
An example:
function changeParam(x, y, z) {
x = 3;
y = "new string";
z["key2"] = "new";
z["key3"] = "newer";
z = {"new" : "object"};
}
var a = 1,
b = "something",
c = {"key1" : "whatever", "key2" : "original value"};
changeParam(a, b, c);
// at this point a is still 1
// b is still "something"
// c still points to the same object but its properties have been updated
// so it is now {"key1" : "whatever", "key2" : "new", "key3" : "newer"}
// c definitely doesn't point to the new object created as the last line
// of the function with z = ...
Solution 3
Yes, Javascript always passes by value, but in an array or object, the value is a reference to it, so you can 'change' the contents.
But, I think you already read it on SO; here you have the documentation you want:
http://snook.ca/archives/javascript/javascript_pass
Solution 4
- Primitive type variable like string,number are always pass as pass by value.
Array and Object is passed as pass by reference or pass by value based on these two condition.
if you are changing value of that Object or array with new Object or Array then it is pass by Value.
object1 = {item: "car"}; array1=[1,2,3];
here you are assigning new object or array to old one.you are not changing the value of property of old object.so it is pass by value.
if you are changing a property value of an object or array then it is pass by Reference.
object1.item= "car"; array1[0]=9;
here you are changing a property value of old object.you are not assigning new object or array to old one.so it is pass by reference.
Code
function passVar(object1, object2, number1) {
object1.key1= "laptop";
object2 = {
key2: "computer"
};
number1 = number1 + 1;
}
var object1 = {
key1: "car"
};
var object2 = {
key2: "bike"
};
var number1 = 10;
passVar(object1, object2, number1);
console.log(object1.key1);
console.log(object2.key2);
console.log(number1);
Output: -
laptop
bike
10
jfriend00
25 years of software coding and management. Now, retired.
Updated on July 08, 2022Comments
-
jfriend00 almost 2 years
I'm looking for some good comprehensive reading material on when JavaScript passes something by value and when by reference and when modifying a passed item affects the value outside a function and when not. I'm also interested in when assigning to another variable is by reference vs. by value and whether that follows any different rules than passing as a function parameter.
I've done a lot of searching and find lots of specific examples (many of them here on SO) from which I can start to piece together pieces of the real rules, but I haven't yet found a single, well written document that describes it all.
Also, are there ways in the language to control whether something is passed by reference or by value?
Here are some of the types of questions I want to understand. These are just examples - I'm actually looking to understand the rules the language goes by, not just the answers to specific examples. But, here are some examples:
function f(a,b,c) { a = 3; b.push("foo"); c.first = false; } var x = 4; var y = ["eeny", "miny", "mo"]; var z = {first: true}; f(x,y,z);
When are the contents of x, y and z changed outside the scope of f for all the different types?
function f() { var a = ["1", "2", "3"]; var b = a[1]; a[1] = "4"; // what is the value of b now for all possible data types that the array in "a" might hold? } function f() { var a = [{yellow: "blue"}, {red: "cyan"}, {green: "magenta"}]; var b = a[1]; a[1].red = "tan"; // what is the value of b now and why? b.red = "black"; // did the value of a[1].red change when I assigned to b.red? }
If I want to make a fully independent copy of an object (no references whatsoever), what's the best practice way to do that?
-
Admin almost 13 yearsWhile technically true, I prefer to say JavaScript is Pass By Object Sharing. It avoids such confusion and moves to a "high level" view.
-
Admin almost 13 yearsWhile technically true, I prefer to say JavaScript is Pass By Object Sharing. It avoids such confusion and moves to a "high level" view.
-
nrabinowitz almost 13 years@pst - That makes sense, but note the issues raised in the referenced Wikipedia page - most people don't use the term, and the (large) Java community calls this "pass-by-value". Still, I agree that it's a bit confusing.
-
tkane2000 about 10 yearsI made a fiddle to play around with this a bit: jsfiddle.net/tkane2000/7weKS/1
-
MEMark almost 10 yearsWhat "confusion" are you referring to? To me "pass-by-value" is perfectly clear.
-
Dan Dascalescu over 9 yearsThe example in this question that this one duplicates, shows an even more interesting case:
c = {first: '5'}
. After executingf(x, y, z)
, z will remain{first: true}
. -
newacct over 9 yearsNope. Everything is pass by value, always.
-
Mukund Kumar over 9 yearsjust put above code in your console and see...value got change..
-
jfriend00 over 9 yearsThere's a time honored terminology debate about calling what Javascript does "pass by reference". I prefer to side step that debate and call what JS does for objects and arrays "pass by pointer". Arrays and Objects are always pass by pointer. If you modify what was passed in (accessing the pointer), the original is modified. If you assign a different array or object to the pointer variable, then the original is not modified because your variable now "points" to a different array or object. Much of this is a "terminology debate", because there is no debate about what actually happens.
-
jfriend00 over 9 years@newacct - And for those that like to claim "everything is pass by value", that doesn't help newbies understand the issue in any way no matter how technically correct you might think you are at some level. Any good explanation has to explain the difference between how objects and primitives are passed such that a newbie understands the difference in practical use since the goal in a question and answer like this is a clear explanation that can be put to use for those who don't understand the finer implementation details or technical meaning of terms.
-
newacct over 9 years@jfriend00: The thing is, there is nothing special about "passing". It works the same way as assigning or any other operation. Once you understand that all values are either primitives or pointers to objects, and not talk about "objects" as values themselves, then there is no confusion. Also, the semantics of passing and assigning in JavaScript are identical to those in Java. And "everything is pass by value" is pretty much how Java is generally described on StackOverflow, combined with explanation how all non-primitives are pointers to objects.
-
jfriend00 over 9 years@newacct - the point here is to explain to people who aren't sophisticated developers and saying everything is "pass by value" without a lot more explanation just simply isn't enough. It doesn't explain the difference in how a primitive and an array are passed or assigned. You can argue it's technically correct, but it's an insufficient explanation for non-sophisticated developers. Your very comment that "once you understand ..." shows that it isn't sufficient until you understand other things - thus you can't just say "everything is pass by value" to a newbie and be done.
-
newacct over 9 years@jfriend00: But I am not answering a question here. I am commenting on a statement made in an answer. If I were writing an answer it would have much content. But here I am just simply pointing out the statement I think is wrong without including tons of stuff which may get off topic.
-
Amit Tomar over 8 years
Changing the value of a variable never changes the underlying primitive or object. However, changing a property of an object referenced by a variable does change the underlying object.
These two sentences put together remove so many doubts. Thank you! -
shyammakwana.me about 8 years
Array
is a object so will change also. -
Rafael about 8 yearscoming from c, this is stupid and annoying, state state state...
-
ralixyle almost 7 years
var users = [1,2,3,4]; var x_users = users; x_users.push(5);
now users and x_users are the same since it's passed by reference. One way to fix this would bevar x_users = users.slice(0); x_users.push(6);
now users and x_users are different since x_users is not referring to users. Took me a while to figure it out :-) Hope this may help someone. -
StanE over 6 yearsWhich is funny, because in JavaScript everything is considered to be an object...
['hi','ho'].length
,(4).toString()
,'Hi'.length
-
doubleOrt over 6 yearsSo, all JavaScript primitives are immutable, and all values are "by sharing" (as stated by @user166390). So, for primitives, it does not matter at all, but I assume passing everything by reference is more efficient performance-wise (since stuff isn't copied over everytime), and objects are obviously not duplicated during an assignment, could we then state that "everything in JavaScript is by reference" (or "by sharing") ? I know it is the exact opposite of what you state, but the concept is essentially the same and this seems more true given that primitives are immutable.
-
doubleOrt over 6 yearscontinuing see this Wikipedia page which states that all JavaScript values are reference types (and take a peek at the spec source for that statement as well). But then, how can this coexist with the fact that sometimes values are stored in the stack not the heap ?
-
Hritik over 5 yearsComing from C, it seems in all calls pointers to a certain memory (object) are passed.
-
Hritik over 5 yearsExcept nearly everything in JavaScript is an object.
-
nnnnnn over 5 years@Hritik - Except for all of the primitive values that are not objects.
-
JWess over 4 years"pass by copy of reference" is the most accurate way to describe how non-primitives are passed into a function. This implies that the original reference variable (from outside the function) is not accessible inside the function...but a copy of this reference variable IS available. This is why the original reference variable cannot be changed from inside the function to point at a different object, but the original object's properties can be edited, because our copied reference variable is still pointing at that same object.