How To Do argumentcollection With JavaScript Functions

How To Do argumentcollection With JavaScript Functions

Posted by Brad Wood
Feb 08, 2009 05:40:00 UTC
As of ColdFusion 8 we have been able to pass a struct into a method so it becomes the method's argument collection without knowing the individual keys in the struct.
[code]myObject.myMethod(argumentcollection=myStruct);
[/code]
The other day I needed to do this in JavaScript. It took me a short while to figure it out, so I thought I would blog it here for others' benefit.In my particular example, I was passing around a reference to a function that I needed to call later with an unknown number of parameters. The answer came in the form of the apply() method which is automatically inherited by all JavaScript functions. The apply method allows you to call a function and pass in two things: The "this" scope you want it to use, and an array of arguments. In my instance I didn't care about the this scope (It can be a very handy way to simulate inheritance but that's another story) so I just passed in an empty object. Below I have an example which is simple enough not to make any real-world sense, but it gets the point across.
[code]<script LANGUAGE="JavaScript" TYPE="text/javascript">
    function foo()
		{				
			for(var i=0; i&lt;arguments.length; i++)
				{
					alert(arguments[i]);
				}
		}
		
	function callIt(callThis,passInThese)
		{
			callThis.apply({},passInThese);
		}
		
</script>
<button onclick="callIt(foo,['Hello','World']);">Button 1</button> &nbsp;&nbsp;&nbsp;
<button onclick="callIt(foo,['Goodbye','Cruel','World']);">Button 2</button>
[/code]
    Both buttons will ultimately result in the foo function being called with two different set of arguments via the callIt function which knows nothing of foo nor its requirements. A few notes:
  • I cannot verify if there are any bad side effects of using apply() this way-- I just know it works.
  • This may also be possible with the use of eval() but I like this better.
  • I didn't specify the arguments to foo in its declaration, but there is nothing keeping you from doing it. If you did, you would be able to refer to your arguments by name as opposed to looping over the argument array like I did.
  • Notice that argumentcollection is a struct in ColdFusion, but an array in JavaScript. The benefit with ColdFusion is you can pass in a struct of arguments and still refer to them all by name without declaring them in your method definition. In JavaScript if you pass in an array of arguments and DON'T define them in the function declaration (like my example above), you must use array notation to get to them.

Henry Ho

Why don't u call the function by apply()? instead of hiding apply in the weird CallIt() method?

Since you're writing JS code, I'd prefer writing it in the JS style instead of making JS works like CF. :)

Brad Wood

@Henry: This was just an example and I agree that it doesn't make much sense when taken by itself. It wasn't intended to look like ColdFusion either. I compared it to argumentcollection because that is meaningful to ColdFusion programmers who are the prevalent audience of this blog.

In my particular use case I had an intermediate, generic function (with a much better name than callIt) which was delegating my function calls. I seriously considered including the full example (which would have given the larger picture) but decided against it since it wasn't relevant to the specific functionality I was demoing and would have been more difficult to understand.