Reputation: 5645
First of all, it is my understanding that appart from some syntax javascript and actionscript operate in a very similar way regarding functions. And in both languages I have the need to add a local variable to an event listener of some sort. for example in actionscript:
public class Foo {
public function handleBar():void {
this.bla(); this.blabla();
}
public function createButton():void {
SomeSortOfButton button = new SomeSortOfButton();
//HERE COMES THE AWKWARD PART:
button.addEventListener(MouseEvent.CLICK,
(function (foo:Foo) {
return function (event:MouseEvent):void {
//I want to do stuff with foo, hence the function that returns a function.
foo.handleBar();
};
})(this)
);
}
}
And in javascript (+jquery) I have something like this from time to time:
var foo = ......;
$("#button").click(
(function(bar) {
return function(event) {
//do stuff with bar (which is defined as foo in the first line)
};
)(foo)
);
I like the way this works, but regarding syntax, it is a complete no go imho. Is there any alternative? What I tried in actionscript was using a default parameter in the handler:
public class Foo {
public function handleBar():void {
this.bla(); this.blabla();
}
public function createButton():void {
SomeSortOfButton button = new SomeSortOfButton();
//HERE COMES THE ALTERNATIVE:
button.addEventListener(MouseEvent.CLICK,
function (event:MouseEvent, foo:Foo = this):void {
//I want to do stuff with foo, hence the function that returns a function.
foo.handleBar();
}
);
}
}
But that is not allowed, because this in foo:Foo = this cannot be resolved at compile time. Fair enough, but I still wonder, is there syntax sugar for the construction described above, in either or both javascript and actionscript? I strongly prefer to use a single function, instead of a function that returns a function.
I would expect an answer to be in the form of: "(To the best of my knowledge,) There is no other way to pass local variables" or "Yes, you can do this: ....".
But of course, any comment is very much appreciated!
Upvotes: 0
Views: 123
Reputation: 1074495
This is a classic example of the need for a "curry" function. The Prototype library has one, but it's very easy to roll your own as well:
function curry(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return func.apply(this, Array.prototype.concat.apply(args, arguments));
};
}
Then in your JavaScript example:
var foo = ......;
$("#button").click(curry(function(bar, event) {
//do stuff with bar (which has the value of `foo` as of when we hooked up the handler)
}, foo));
ES5 has Function#bind
, which is used for setting the this
value in a function, but which can also be used for currying. But if you use Function#bind
, you can't have this
just get passed through (which is what the curry
above does: it calls the function with whatever this
value it was called with, instead of a specific one).
That's in the general case. In the specific case of a jQuery event handler, jQuery gives you a way to do that:
var foo = ......;
$("#button").click({bar: foo}, function(event) {
//do stuff, using event.data.bar
});
You have to use an object with click
, but you can use other things if you use on
instead.
Upvotes: 1