I'm new to JavaScript (though experienced in C++), and today, I wrote something like this:
function foo(bar) {
bar = "something else";
}
var x = "blah";
foo(x);
alert(x); // Alerts with "blah", but I was expecting it to alert with "something else"
This confused me a lot, as I've been watching some JavaScript videos by Douglas Crockford, and remember him saying something like "JavaScript is always pass by reference".
The way I can explain this situation is that JavaScript passes references to objects, but those references are copied. This would mean in the foo
function, I am assigning a new reference to bar
, which then goes out of scope, leaving to reference that x
has left untouched. Essentially we start with:
x ---->"blah"
Then when foo
is called, bar
references the same data:
x ---->"blah"
bar -----^
So when "something else" is assigned to bar
, this happens:
x ---->"blah"
bar ---->"something else"
Is that an accurate model of what is actually happening in JavaScript, or am I missing something else?
As an extra question, is there any way to say, change the data referenced by this variable? Is this a situation that comes up often, or can it be easily avoided?
Edit:
Douglas Crockford in the video I watched says "objects are always passed by reference they're not passed by value", which is correct, but arguments to functions are passed by value, it's just the reference is passed by value.
To pass an object to a JavaScript function, we can add a parameter that accepts an object. const someFunc = (arg) => { alert(arg. foo); alert(arg. bar); }; someFunc({ foo: "This", bar: "works!" });
As mentioned, functions are objects. You can work with functions as if they were objects. For example, you can assign functions to variables, to array elements, and to other objects.
To pass an object as an argument we write the object name as the argument while calling the function the same way we do it for other variables. Syntax: function_name(object_name); Example: In this Example there is a class which has an integer variable 'a' and a function 'add' which takes an object as argument.
Your interpretation is spot on.
First, you have a variable called x
which is a reference to a string object. Let's say that memory is 0x100. x
points to 0x100
, which contains the bytes blah:
var x = "blah"; // x is 0x100 which references a string in memory
Next, you pass 0x100
into the function foo
:
function foo(bar) {
bar = "something else";
}
As everything in JavaScript is passed by value, even references, JavaScript makes a copy of this reference in memory, which is now called bar
within that function:
foo(x); // Copies the value of x (a reference) to bar
At this point, we have two separate variables. x
and bar
. Both happen to have the same value, 0x100
. Thus, if you were to change a property of the object either of those is referencing, it would affect both x
and bar
.
However, what you're doing is assigning bar
to point to something else:
bar = "something else"; // Now references some other string we just created
Now, bar
gets re-assigned to reference a new string we've just allocated memory for. bar
no longer has a value of 0x100
, it now has a value of some other address (say 0x500
). x
of course still has a value of 0x100
since bar
was merely a copy of x
, and not a reference to x
.
For this reason, when you:
alert(x);
You'll still get the original value, as that is what x
is pointing to.
Second question:
is there any way to say, change the data referenced by this variable? Is this a situation that comes up often, or can it be easily avoided?
Yes, just wrap it in another object. For example:
var x = {Value: "blah"};
foo(x);
Now, we have a reference to an object with a property called Value
, which contains a reference to a string in memory somewhere.
In foo
, we can do:
bar.Value = "something else";
Which will affect the Value
property of x
, since both bar
and x
referenced the same object, and you never changed the value of either of them.
In other words, you cannot re-assign the reference you're passing into a function, since you're simply re-assigning a copy. You can, however, change a property of an object being referenced, since other copies of that reference all point to the data you're changing.
Your interpretation is correct.
You can change the values of keys in an object, which lets you do something similar to pass-by-reference:
function foo(bar) {
bar.msg = "something else";
}
var x = { msg: "blah" };
foo(x);
alert(x.msg);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With