Herbert
Herbert

Reputation: 5645

Add a local variable to an actionscript or javascript function

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

Answers (1)

T.J. Crowder
T.J. Crowder

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

Related Questions