0

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!

3
  • It's really hard to tell what you're trying to achieve. In your JavaScript example, you're jumping through hoops to avoid having your event handler use foo. Why? Because you're going to change foo later? Commented May 9, 2013 at 9:44
  • If you reference foo in the eventhandler, that is within the {} of the inner function, this will only work if foo is a global variable. Moreover, foo might also change like you said. Commented May 9, 2013 at 13:48
  • @ Herbert: No, foo doesn't have to be a global. It just has to be in scope where the function is defined. Globals are just a special case of that general principle. More: Closures are not complicated Commented May 9, 2013 at 14:56

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.