Reputation: 41393
I'm clearly missing something here.
I need to fill methods of dynamic AS3 class from an array (see silly example below).
But when I call those methods, all of them appear to be the same method. In the example below, all methods are foobar1
.
If I create methods by hand, without a loop, everything is fine.
Any clues?
package foo
{
public class Bar
{
public function testDynamicClassSanity():void
{
var foo:Foo = new Foo();
var methods:Object = { foobar1: 101, foobar2: 201, foobar3: 301 };
for (var key:String in methods)
{
var val:Number = methods[key];
foo[key] = function():Number
{
return val;
};
}
// Next trace prints
// 101 = 101 201 = 101 301 = 101
trace(
101, "=", foo.foobar1(),
201, "=", foo.foobar2(),
301, "=", foo.foobar3()
);
}
}
}
internal dynamic class Foo
{
};
Upvotes: 0
Views: 3162
Reputation: 28409
I think that your problem is the scoping of the var variable. Try this modification:
for (var key:String in methods)
{
var val:Number = methods[key];
foo[key] = function (valInternal:Number) {
return function():Number
{
return valInternal;
};
}(val);
}
(the above trick works in Javascript to workaround a similar problem... I bet it is applicable to AS3)
Upvotes: 2
Reputation: 10665
I would guess the problem is in the scoping of val
-- you assume its scope is the for loop, but that is not the case in AS3, the scope is the function. Am I correct that all your calls return 301?
Update: As working around the issue that you are experiencing (the variable val
being referenced and only later resolved instead of being 'copied' into your function) is quite cumbersome: Depending on your use case you could inspect the method calls and just look up the desired result in the table using the functionality provided by Proxy.
Upvotes: 4
Reputation: 41393
For the records, I'll post here the corrected version of the testDynamicClassSanity()
function:
public function testDynamicClassSanity():void
{
var foo:Foo = new Foo();
var methods:Object = { foobar1: 101, foobar2: 201, foobar3: 301 };
// We have to introduce new scope
var makeCallback:Function = function(result:Number):Function
{
return function():Number
{
return result;
}
}
for (var key:String in methods)
{
foo[key] = makeCallback(methods[key])
}
// Prints as intended
// 101 = 101 201 = 201 301 = 301
trace(
101, "=", foo.foobar1(),
201, "=", foo.foobar2(),
301, "=", foo.foobar3()
);
}
Upvotes: 1