I thought it would be fun to do a back-to-basics kind of post on the JavaScript language and base it on my second most popular blog post of all time, Parameter passing in C#.
In other words, this post will present some JavaScript brain teasers around parameter passing and visually illustrate the solutions.
Since JavaScript doesn't have the ref
or out
keywords like C#, we'll just be looking at:
- Primitive Values
- Reference Values
- Strings (Immutable Values)
- Passing Primitives
- Passing References
Primitive Values
Starting simple, what's the result of the following, and why?
var i = 5;
var j = i;
j = 10;
alert(i);
Let's take it line by line. On the first line, we declare a variable i
and assign it the value 5
. 5
is a value of type 'number
', and number is a one of a handful of primitive types including undefined, null, boolean, and string.
On the second line, we declare a new variable j
and assign it the value held by the variable i
. If we think of variables as small containers (boxes) that can only contain primitives or references, then we can picture the first two lines of code like this:
If JavaScript were pass by reference, then j
might contain a pointer to i
. But because JavaScript is pass by value for primitives, the second line copies the value in i
into the box for j
(copying is illustrated with the blue line).
Consequently when we assign j
the value 10
, it doesn't affect what's in the box for i
.
Thus the answer to alert(i)
is 5
.
Reference Values
So what is the result of the following, and why?
var i = { a: 5 };
var j = i;
i.a = 10;
alert(j.a);
In this example, we declare a variable i
and assign an object to it. Consequently, i
contains a reference value. Reference values are essentially pointers to objects (which are in turn aggregations of properties). In a language like C#, they'd be like a pointer on the stack to an object on the heap (although technically JavaScript doesn't have a stack or a heap).
So on line two, we then instantiate a variable j
and assign to it the value that's in i
. Illustrating the pointer as an arrow, we end up with this:
If JavaScript were pure pass by value, then j
might have contained a complete copy of the object. But JavaScript, like Java, Python, Ruby, and C# is technically call by sharing, which means that for reference values, we treat the pointer as pass by value, and thus the object it points to as pass by reference.
Consequently, when we assign anything to j.a
, we follow the pointer to the shared object, and get this:
And that's why alert(j.a)
returns 10
.
Strings (Immutable Values)
How about this:
var s1 = 'hello';
var s2 = s1;
s2 = 'world';
alert(s1);
In C#, string
s are immutable reference types. In JavaScript, however, they're just primitive values, which are all immutable. So it's kind of a trick question and this turns out to be identical to our first example.
Thus alert(s1)
is simply 'hello
'.
Passing Primitive Values
Let's expand what we've learned about primitives to functions:
function Change(j) {
j = 10;
}
var i = 5;
Change(i);
alert(i);
If you guessed that this is almost identical to our first example, you're absolutely right. Illustrating it roughly how the interpreter would see, it would result in this:
Thus alert(i)
is 5
.
Passing Reference Values
Finally, we can explore how reference values get passed with something like this:
function Change(j) {
j.a = 10; } var i = { a: 5 }; Change(i);
alert(i.a);
If you're thinking this is nearly identical to our second example, you're right. Illustrating it roughly how the interpreter would see it would result in this:
Thus alert(i.a)
gets us 10
.
Double Bonus Points
You're tied up in double overtime with one second left on the clock:
function Change(j) {
j = { a: 10 };
}
var i = { a: 5 };
Change(i);
alert(i.a);
Go ahead, hit F12 .... nothing but net! ... and the crowd goes wild!
Hope you had fun reading this and hopefully learned something new. Please post in the comments or hit me up on twitter if something doesn't look right.
CodeProject