The arguments
object in JavaScript looks like an array, but really it is just an array-like object. It has a length
property that returns the number of arguments supplied to the calling function. And callee
, which actually returns the calling function. Like an array, you can access the elements using an index:
// Remember, in JavaScript you can pass as many arguments // to a function as you want. function example() { for(i=0; i < arguments.length; i++) { console.log(arguments[i]); } } example(true, false, 'hello', { foo: 'bar' }); // => true // => false // => 'hello' // => { foo: 'bar' }
Rubyists, think *args
. By allowing for optional parameters we can clean up our code interface and make it more flexible. Our methods can be more dynamic and ultimately become more useful. Lets take a look at an example, a basic getter and setter. Say we have a private variable called _status
. If we want to access that value, you could do something like:
// setter function setStatus(status) { return _status = status; } setStatus('started')); // => 'started'
and
// getter function getStatus() { return _status; } getStatus() // => 'started'
…or you could use one method to do both:
// getter/setter function status() { return arguments.length > 0 ? _status = arguments[0] : _status; } status(); // => 'pending' status('started'); // => 'started'
The first part:
arguments.length > 0
Just checks to see if there are any arguments. If so, then it assigns the first argument to the private variable:
_status = arguments[0]
Otherwise, it just returns the private variable.
Again, thinking *args
; arguments
can be used to pass arguments straight through from one method to another. Say I am making a state machine in JavaScript. I want to be able to register states with callback functions that are triggered when the state is transitioned to. The interface for registering states might look something like this:
Mail.registerStates( 'started', 'finished', { // State with optional callback function 'sent' : function(recipient) { return 'Mail sent to ' + recipient }; } );
When we execute the state’s callback function we can pass in the arguments:
// changes the state from 'finished' to 'sent', arguments are passed // straight-through to the callback function Mail.send('gob.bluth@gmail.com'); // Somewhere in the code // Execute the callback function, pass the context and arguments objects fnct.apply(this, arguments);
apply()
takes the context, then an array (or array-like object) that expands as the arguments for the applicable function.
There are many possibilities with arguments
, but converting it to an array provides even more flexibility. I’ve recently discovered this trick:
var args = [].concat(arguments);
Apparently arguments
is enough of an array that we can operate on it with methods like concat
.
That’s all for now, keep your eyes open for more articles on the dynamic features of JavaScript.