Javascript Pass By Reference Arguments

When learning a new programming language, one important question is always “does language X pass arguments by value or by reference?” Javascript behaves closely to Java in its treatment of arguments – in that all types are passed by value.

However for certain types (like object types), a pointer is passed in by value – giving you access to modifying the dereferenced argument object within the called function. I’m assuming you already know what pointers and dereferenced data means. People from a C/C++ background will be most familiar.

Let’s see some code to make more sense of the formal statement above.

var a = {},
    foo = function (obj) {
      obj.bar = 'bar';
    };

foo(a);
console.log(a); // Output is {bar: 'bar'} not {}

We start by initializing a to an empty object. We had to use an object here to exhibit the pointer manipulation behavior. Had the value been a number or string, it would be passed by value purely. In other words, a copy of that value would have been made and we couldn\’t do anything interesting to it.

We then create a dummy function foo that accepts an argument and then adds the attribute bar to the passed in object. The value for the attribute is trivially set to the string 'bar'.

Next, we call our newly created foo() function with the variable a as an argument. This triggers a pointer/reference to the object contained in a to be passed into foo. Within the foo function, that object passed in is aliased/renamed to be obj.

The next point is the most important one. We’re adding an attribute to the object pointed to by the copy of the passed in reference, obj. If we had simply reassigned obj to some other value, then we would be reassigning the copy to some value. Since obj is a variable that exists only within the definition of the foo function, it will be destroyed when leaving that function (scope). This leaves the original, outside object a untouched.

Here’s some code to clarify:

var a = {},
    foo = function (obj) {
      // Reassign the reference copy, obj, to a new object
      obj = {bar: 'bar'};
    };

foo(a);
console.log(a); // Output is {}

When adding an attribute to the object via the pointer, as in our previous obj.bar = 'bar', we’re asking that pointer to go back to the object that it points to and add the bar attribute with a value of 'bar'. This directly modifies the outside object a, which was being pointed to by obj within foo().

Hopefully you’re still with me!

This discussion is really important when it comes to building larger applications with javascript. We tend to pass around objects to functions of other objects to keep some synchronization between objects in our system.

For example, if you want to have two objects be notified when some event occurs, you can have them register themselves (latch on) to some shared object. Again, since objects can be modified within functions and have those modifications preserved outside the function, we can share data between those registering objects.

This idea gets used extensively in Backbone.js routing and events – where various views need to be notified and act on triggered routes or user-defined events.

I hope this helps to clarify reference arguments. Let me know if you have any specific questions below.