Passing JavaScript Function Arguments by Reference

By Rob Gravelle

11/27/2012

There are two ways that a function argument, or parameter, can be passed to it: by value or by reference. In the first instance, a copy of the variable is made when the function receives it. Hence, any changes made to the passed variable within the function end when the function returns or exits for whatever reason. When a variable is passed to a function by reference, a pointer is assigned to the variable in question so that any changes to it within the function are applied globally. In this article, we're going to learn how to pass primitive data to a function by reference. The next instalment will cover passing objects by value.

Function Scope

When a variable is passed to a function by value, a copy is created within the function signature, where the received variable is created. From then on, the opening and closing curly braces act as scope delimiters. The variable is then garbage collected once the function has terminated:

function myFunction(arg0 /*arg0 is the copied variable */) {
  arg0 += 10;
  console.log(aVar); //displays 15
} //goodbye arg0…

var aVar = 5;
console.log(aVar); //displays 5
myFunction(aVar);
console.log(aVar); //still displays 5

Note that naming the function parameter the same as the actual variable will have no effect, because the function has its own scope.

Some languages give you the option of specifying whether you want to pass an argument by reference or by value, usually at the function. For instance, PowerShell includes the [ref] prefix for this purpose; Visual Basic has(had) the ByVal and ByRef keywords. Object-Oriented languages are more rigid in their handling of function arguments. They tend to pass all primitives by value and all objects by reference. This is understandable behavior seeing as objects can be quite large and therefore memory-intensive if they were copied by every function. In the above example, we know that aVar will be passed by value because it is an integer. Loose typing or not, JavaScript uses the best data type for the job, depending on the value. In fact, you can bet that any simple value will be stored as a primitive type of some sort.

That behavior also applies to the properties of an object, so long as it is itself a simple data type. You can therefore pass an object's property to a function if you don't need to change it globally or require the rest of the object:

function myFunction(arg0) {
  arg0 = "I'm still a string!";
  console.log(arg0); //displays "I'm still a string!"
}

var aVar = {val: "I'm a string!"};
console.log(aVar.val); //displays "I'm an object!"
myFunction(aVar.val);
console.log(aVar.val); //displays "I'm a string!"

In this case, the val property will be passed to the function by value because the data type of the val property is a primitive (a string):

"But isn't a string an object?" you might ask. After all, it does have methods and a length property. Good catch! In fact, Strings in Javascript are indeed passed "by reference". Thus, calling a function with a string does not involve copying the string's contents. However, JavaScript Strings are immutable; in contrast to C++ strings, once a JavaScript string has been created it cannot be modified. Hence, when you change a string in your code, you're actually creating an entirely new string variable.

Converting Primitives to Objects

To override the default behavior of passing primitives to functions by value, we have to convert the variable to a true Object so that the function does not copy it. In JavaScript it's actually easier than in a language like Java, where you'd have to pass it to its object wrapper - i.e., Integer for ints, Boolean for booleans, etc. JavaScript's base Object constructor accepts any primitive type and will convert it into an Object for us!

Promoting a primitive to an Object in this way gives us access to an object's toSource(), toString(), and valueOf() methods. All we have to do is set each of those to a new function that returns our updated value and presto-chango, the value is updated globally:

function modifyVar(obj, val) {
  obj.valueOf = obj.toSource = obj.toString = function(){ return val; };
}
 
var myString = 'string 1';
    myString = Object(myString);   //convert into an object.
modifyVar(myString, 'new string'); // modify the contents via reference
console.log(myString);             // displays 'new string'

Conclusion

As we saw here today, converting a primitive into an object for passing by reference is fairly easy to do using the Object() constructor. Passing objects to a function by value on the other hand, requires a little more effort. That's what we'll be looking at in the next instalment.




Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date