JavaScript for C# programmers: the arguments array

A slight diversion in our quest to learn JavaScript from a C# programmer's perspective.

This episode is about the arguments array.

In C#, if we want to write a method that takes an undefined (at least at compile-time) number of parameters, we use the params keyword and declare a parameter array.

    static void ListArgs(params string[] args) {
      Console.Write(string.Format("There are {0} parameters: ", args.Length));
      for (int i = 0; i < args.Length; i++) {
        Console.Write(args[i] + " ");
      }
      Console.WriteLine();
    }

    static void Main(string[] args) {
      string[] words = {"one", "two", "three"};

      ListArgs(words);
      ListArgs("hello", "world");
      ListArgs();

      Console.ReadLine();
    }

Here we have a ListArgs method whose only parameter is a parameter array of strings, called unimaginatively args. The method merely outputs the number of parameters, and the values of each of them. The Main method calls this method in three different ways, first with an array of strings, then with two string parameters, then with nothing at all. In the first case, the compiler ensures the method is called with the given array. In the second case, the compiler inserts code to create an array containing the two parameters, and then calls ListArgs. In the third case the compiler creates an empty array and passes it in.

In all cases, the output is as we expect.

In JavaScript, no matter how we declare the parameters to a function, when we call it we always get a variable called arguments automatically created for us that contains all the parameters passed in.

One reason for this is that JavaScript is very loose in how it treats parameters. If you declare a function with two parameters, say, you can call it with exactly two parameters as you'd expect, but you can also call it with fewer than two parameters, or with more than two parameters. In the first case, any parameters that were not provided by the caller will be set to undefined inside the function; in the second case, the extra parameters are just ignored.

Nevertheless, in that second case, we can discover the extra parameters by using the arguments array. JavaScript will construct this pseudo-array to contain all the parameters passed to the function.

Here's the JavaScript equivalent of the ListArgs method:

var ListArgs = function() {
    var logstring = "There are " + arguments.length + " parameters: ";
    for (var i = 0; i < arguments.length; i++) {
        logstring += arguments[i] + " ";
    }
    console.log(logstring);
};

ListArgs("hello", "world");
ListArgs();

The call with a string array doesn't really translate: we'd have to check internally to the function to see if a particular parameter were an array and deal with it accordingly. Anyway, you can see that ListArgs is defined not to accept any formal parameters at all. Nevertheless, we can get at them by using the arguments pseudo-array.

I want to stress that arguments, although it looks like an array, isn't. It's an object, certainly, and it has a length property and its properties are numbers sequentially increasing from '0', but that's only as deep as the deception goes. A lot of times, it doesn't really matter that arguments is not an array (those properties I mentioned are usually enough to be getting on with), but sometimes you'll find yourself caught out and need some array methods. In that case you'll have to copy the elements to a real array, or you'll have to use the apply method to use an array method on the arguments object.

Because arguments (and this for that matter) are created when a function is called, they are locked in scope to that call of that function. They do not participate in the normal function scoping. Which is obvious, if you think about it: if you have a function B nested in function A, then any reference to arguments in B will use B's arguments object and not A's. If you want to share A's arguments with B, then you'll need to copy them to a local variable in A.

Album cover for (the best of) New Order Now playing:
New Order - World
(from (the best of) New Order)


Loading similar posts...   Loading links to posts on similar topics...

4 Responses

#1 Dew Drop – March 9, 2009 | Alvin Ashcraft's Morning Dew said...
09-Mar-09 5:37 AM

Pingback from Dew Drop – March 9, 2009 | Alvin Ashcraft's Morning Dew

#2 JavaScript for C# programmers: the arguments array : Algorithms for the masses - Julian M Bucknall said...
09-Mar-09 6:05 PM

Thank you for submitting this cool story - Trackback from DotNetShoutout

 avatar
#3 Saeed Neamati said...
29-Dec-11 1:06 AM

Good article, thanks. However, I now need a method to dynamically get the list of all parameters passed to a method, and then loges them all. For example, I'd like to have:

public void GetFullName(string firstName, string lastName)
{
  Logger.LogParameters();
} 
julian m bucknall avatar
#4 julian m bucknall said...
03-Jan-12 11:58 AM

Saeed: I have this down as a quick blog post this week. Stay tuned!

Cheers, Julian

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response