14

Is it possible to call a function in AS3 using a string value as the function name e.g.

var functionName:String = "getDetails";

var instance1:MyObject = new MyObject();

instance1.functionName(); // I know this is so wrong, but it gets the point accross:)

UPDATE

The answer from @Taskinoor on accessing a function is correct:

instance1[functionName]();

And to access a property we would use:

instance1[propertyName]
Drenai
  • 11,315
  • 9
  • 48
  • 82

3 Answers3

23
instance1[functionName]();

Check this for some details.

taskinoor
  • 45,586
  • 12
  • 116
  • 142
  • Nice one, was difficult to google for an answer, this is what I was after. – Drenai Dec 20 '10 at 12:02
  • 7
    Just to piggyback on this, you can ask the instance if it has a function or var using the `in` keyword: `if(functionName in instance1)` – Brian Genisio Dec 20 '10 at 13:05
2

You may use function.apply() or function.call() methods instead in the case when you dont know whether object has such method for instance.

var functionName:String = "getDetails";
var instance1:MyObject = new MyObject();
var function:Function = instance1[functionName]
if (function)
    function.call(instance1, yourArguments)
iklubov
  • 21
  • 3
  • As a side note, the advantage here is that apply() allows you to pass the parameters in an array instead of specifying them inline. – Luis Jun 17 '14 at 16:03
  • @Luis: See my [answer](http://stackoverflow.com/a/27822620/1762224) below. You can still specify them inline by passing the `...args`. You just have to make sure that the switch can handle the length of arguments. – Mr. Polywhirl Jan 07 '15 at 17:32
1

I have created the following wrappers for calling a function. You can call it by its name or by the actual function. I tried to make these as error-prone as possible.

The following function converts a function name to the corresponding function given the scope.

public static function parseFunc(func:*, scope:Object):Function {
    if (func is String && scope && scope.hasOwnProperty(funcName)) {
        func = scope[func] as Function;
    }
    return func is Function ? func : null;
}

Call

Signature: call(func:*,scope:Object,...args):*

public static function call(func:*, scope:Object, ...args):* {
    func = parseFunc(func, scope);
    if (func) {
        switch (args.length) {
            case 0:
                return func.call(scope);
            case 1:
                return func.call(scope, args[0]);
            case 2:
                return func.call(scope, args[0], args[1]);
            case 3:
                return func.call(scope, args[0], args[1], args[2]);
            // Continue...
        }
    }
    return null;
}

Apply

Signature: apply(func:*,scope:Object,argArray:*=null):*

public static function apply(func:*, scope:Object, argArray:*=null):* {
    func = parseFunc(func, scope);
    return func != null ? func.apply(scope, argArray) : null;
}

Notes

Call

The switch is needed, because both ...args and arguments.slice(2) are Arrays. You need to call Function.call() with variable arguments.

Apply

The built-in function (apply(thisArg:*, argArray:*):*) uses a non-typed argument for the argArray. I am just piggy-backing off of this.

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132