JavaScript for C# developers: converting arguments into an array

Way back in March 2009, I wrote a quick post about the JavaScript arguments quasi-array, about how the interpreter sets it up on every call to every function to hold the arguments passed to that function.

Brown paper wrapped parcelAlthough I blithely talked about the fact that arguments was array-like, it wasn’t a real array (it’s not typeof Array) and didn’t have methods like pop() and the like. In fact, it only really has a length property and a bunch of properties named ‘0’, ‘1’, ‘2’ and so on. So it’s easy to iterate over the elements, er, properties, but that’s essentially it.

It’s actually quite easy to convert it to an array and then use that. You don’t even have to use the obvious for loop to do it either. You use the Array’s prototype’s slice() method:

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

Since arguments does not have the slice() method, we have to use the call() function to call it on arguments (this is an application of the apply invocation). slice() returns part of an array as an array, but If you don’t pass any arguments to it – start index, end index – the function returns all of the elements instead. Which is, if you think about it, what we want.

So, if you have, say, a logging library for your code, and you want to log the values of the arguments to a particular function, you could do something like this:

var convertArgs = function (args) {
  return Array.prototype.slice.call(args);
};

var myLoggingLibrary = {
  logArguments: function (argsArray) {
    console.log(argsArray);
  } 
};

var someFunctionToTest = function (a, b, c, d) {
   // do something with the arguments; we’ll just print the first
   console.log(a);
};

var addArgumentsLogging = function (f) {
  return function () {
    var args = convertArgs(arguments);
    myLoggingLibrary.logArguments(args);
    f.apply(this, args);
  };
};

someFunctionToTest(1, 2, 3, false); // prints "1"

someFunctionToTest = addArgumentsLogging(someFunctionToTest);

someFunctionToTest(1, 2, 3, false); // prints "[1, 2, 3, false]" then "1"

With the addArgumentsLogging() function, I am not altering the function to be logged: I am merely creating a wrapper around it that does the logging and then calls the original function using the apply invocation. Notice how I’ve replaced the original function with the wrapped version. (Note also that the addArgumentsLogging function creates a closure over the parameter f.)

So there you go: how to convert the arguments quasi-array into a real array and then use it.

Album cover for Goodbye Country (Hello Nightclub)Now playing:
Groove Armada - Little By Little
(from Goodbye Country (Hello Nightclub))


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

2 Responses

 avatar
#1 Ju said...
07-Jan-12 1:26 AM

You can also use '[].slice.call(arguments,0);' which saves some typing :)

julian m bucknall avatar
#2 julian m bucknall said...
07-Jan-12 7:27 AM

Ju: Cool :) If a smidgeon obfuscated...

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