Wednesday, November 4, 2009

Pass ...rest as a parameter to another function

I recently needed to have a function that accepted a variable number of parameters. This can easily be accomplished using the function myFunction(...rest) syntax. This way I can pass in no parameters (in which case rest is an empty array), one parameter, or multiple parameters.

But, then I wanted to pass those same parameters on to another function that also accepted a variable number of parameters (e.g. ExternalInterface.call(jsFunctionName, ...args)). If you simply call the other function and pass in rest as a parameter then it won't work as expected. E.g.
    public function sayHello(...rest):void {
        // this won't work as expected
        callMe(rest);
    }
    
    private function callMe(...rest):void {
        trace(rest.length + ": ['" + rest.join("' | '""']");
    }

What happens in callMe(...rest) is rest is an array that actually contains only one item - another array which has the rest parameters that were originally passed into sayHello(...rest).
So if you made a call like this:
    sayHello("Hello""World""!");
Then the traced output would be 1: ['Hello,World,!'].
Notice that there is only 1 parameter!

The way to get around this is to use Function.apply(null, args) to call the function instead, like this:
    public function sayHello2(...rest):void {
        // use Function.apply to pass in the rest parameters properly
        var func:Function = callMe; 
        func.apply(null, rest);
    }

So if you made this call now:
    sayHello2("Hello""World""!");
Then the traced output would be 3: ['Hello' | 'World' | '!'].
Now there are 3 parameters as expected.

I found some help on this topic from The Joy Of Flex Blog by David Colleta.