JavaScript: arguments explained

In JavaScript, each function has access to a special variable named arguments which represents any arguments which were used when calling that function.

You don’t have to define or declare arguments, it’s just already there and accessible inside the body of any JavaScript function.

This can lead to some very powerful behavior as you can write a function signature that includes only 1 argument, call the function with more, and have access to those additional arguments. For example:

var hello_name = function(first) {
    return "Hello " + first + " " + arguments[1] + " " + arguments[2];
};

hello_name("Victor", "James", "Quinn");

// Will return
"Hello Victor James Quinn"

Notice how hello_name() only has one argument declared on it, but was called with 3 and it handled all of them! Very cool! (though confusing, I certainly don’t suggest this is a good use of arguments in a case like this!)

A better real world use case is when you want a function to be able to accept an arbitrary number of arguments. Then we can iterate over each item in arguments and do something with each one. For example:

var uppercase_all_names = function() {
    var upper = [];
    for (i=0; i < arguments.length; i++) {
        upper[i] = arguments[i].charAt(0).toUpperCase() + arguments[i].substr(1);
    }
    return upper;
};

uppercase_all_names("victor", "james", "quinn");

// Will return
["Victor", "James", "Quinn"]

This works, but surely we can do better! Let’s get a bit functional with map() and reduce the complexity of that code:

var uppercase_all_names = function() {
    return arguments.map(function (name) {
        return name.charAt(0).toUpperCase() + name.substr(1);
    });
};

// Will return
TypeError: Object #<Object> has no method 'map'

Uh oh, what happened? Why can’t we use the Array map() function? It sure looks like an Array!

This is because arguments is not really an Array in spite of it having .length and being able to index its subitems like an Array.

var is_arguments_an_array = function() {
    // This is one way to check if a thing is an array in JS.
    // Just trust me on this, to explain would be another article.
    return arguments instanceof Array;
};

is_arguments_an_array(4, 8, 15, 16, 23, 42);

// Will return
false

So is it an Object?

var is_arguments_an_object = function() {
    // This is one way to check if a thing is an object in JS.
    // Just trust me on this one too :)
    return typeof arguments;
};

is_arguments_an_object(4, 8, 15, 16, 23, 42);

// Will return
true

I suppose the answer is “kind of.” It is its own special beast that acts like an Object, but which has a length. If we inspect it it looks like an Object whose keys look like Array indices.

var inspect_arguments = function() {
    // This is one way to check if a thing is an object in JS.
    // Just trust me on this one too :)
    console.log(JSON.stringify(arguments));
};

// Will output to console
{"0":4,"1":8,"2":15,"3":16,"4":23,"5":42}

So what do we know thus far:

  1. We have a powerful item
  2. That is its own weird Array/Object hybrid type

But in spite of arguments being weird we can work with it and make things a bit more manageable.

The easiest way to do that is to convert it to an array. This is surprisingly convoluted, but is achieved rather easily with the following snippet:

var args = Array.prototype.slice.call(arguments);

Let’s see it in use:

var convert_arguments_to_array = function() {
    var args = Array.prototype.slice.call(arguments);
    // now args is a proper array!
    return args;
};

convert_arguments_to_array(4, 8, 15, 16, 23, 42);
// Will return
[4, 8, 15, 16, 23, 42]

convert_arguments_to_array(4, 8, 15, 16, 23, 42) instanceof Array;
// Will return
true

Yay! Something we can more reliably work with! Now revisiting our upper case function from above:

var uppercase_all_names = function() {
    var args = Array.prototype.slice.call(arguments);
    return args.map(function (name) {
        return name.charAt(0).toUpperCase() + name.substr(1);
    });
};

uppercase_all_names("victor", "james", "quinn");

// Will return
["Victor", "James", "Quinn"]

arguments is an extremely powerful but often confusing component of JavaScript but hopefully this has helped shed some light on it!

You should follow me on twitter here.

For Reference: EcmaScript official spec on the arguments object

 
154
Kudos
 
154
Kudos

Now read this

LocationKit: The Making of – Part 1

This is part 1 of a 2 part series, stay tuned for the second part! Overview SocialRadar’s free LocationKit SDK for iOS (and soon Android!) provides advanced location technology to offer developers higher accuracy location, lower battery... Continue →