Thursday, February 12, 2015

An illustrated Gude to Parameter Passing in JavaScript

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# strings 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.