Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with:

Arguments.length In Javascript Depends On Invocation Arguments, Not Function Signatures

Posted by Ben Nadel

In Javascript, within a function, you can use "arguments.length" to determine how many arguments were passed-in during the given function invocation. In the past, I've used this to overload Javascript functions. Until I read Eloquent Javascript by Marijn Haverbeke, however, I don't think I had a complete understanding of how the arguments collection worked. In order to drill this information into my head, I wanted to quickly demonstrate that arguments.length relies on the invocation arguments, not the defined parameters (function signature).

Below, I am defining a function signature that contains three parameters. Then, I invoke that function with both less-than and more-than the defined number of parameters.

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Javascript Arguments Depend On Invocation</title>
  • <script type="text/javascript">
  •  
  •  
  • // I am a function that has THREE defined parameters.
  • function test( foo, bar, baz ){
  •  
  • // Log the length of the arguments collection.
  • console.log( arguments.length );
  •  
  • // Log the arguments collection itself.
  • console.log( arguments );
  •  
  • }
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // With less than the number of defined arguments.
  • console.log( "With Two Arguments" );
  •  
  • test( "hey", "cutie" );
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // With more than the number of defined arguments.
  • console.log( "With Four Arguments" );
  •  
  • test( "hey", "there", "cutie", "pie" );
  •  
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Left intentionally blank. -->
  • </body>
  • </html>

When we run this code, we get the following console output:

With Two Arguments
2
["hey", "cutie"]

With Four Arguments
4
["hey", "there", "cutie", "pie"]

As you can see, the arguments collection (including the arguments.length property) depends only on the arguments used during invocation - not on the parameters defined as part of the method signature. Ironically, I've leveraged this fact before; but, like I said, I don't think I was consciously aware of the underlying mechanics.




Reader Comments

Good call, Ben! The whole concept of a method signature doesn't seem very JavaScript, does it? In Java, the signature is critical to method binding. And even Ruby, which lets you get away with anything, complains if you don't uphold the contract in the method signature.

Reply to this Comment

If you do want to know the number of arguments that are defined for a function, so that for example you can compare what you were expecting to what you actually get, you can use something similar to the following:

function fnGreat(arg1, arg2, arg3){
console.log(fnGreat.length == arguments.length);
}
fnGreat(1, 2);

When the function isn't named, such as the following:
var fnGreat = function(agr1, agr2, arg3){
console.log(arguments.callee.length == arguments.length);
}
fnGreat(1, 2);

As "callee" is a reference to the function that was called, you can access that function's length property. According to https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee it is deprecated, so if you want to be sure to get the length of a function, make sure it is a named function.

Reply to this Comment

@David,

And, ColdFusion is kind of in between - you can define a whole bunch of arguments, but mark some of them as optional and even give them default values. It's interesting to see how each language handles this task.

@Danilo,

Yeah, deprecating the "arguments.callee" makes recursion a bit more complex. You can no longer use anonymous functions. Named functions, as you point out, do the trick; but, sometimes, it's superfluous.

Reply to this Comment

@Drew,

Thanks for the link - John always has such elegant solutions. According to the Mozilla Dev Center, I think "function.arity" is being deprecated; not sure about function.length". I've never actually used either in my code yet.... YET! :)

Reply to this Comment

@Ben, yep arity is apparently the CS notion of the arguments of a function. At least that's what I read from some arcane manuscript long before the days of duck punching :D!

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.