3

Consider this HTML:

<p>Click me</p>

I would like to write an object with a click handler for each p, but run into the problem that my click handler function could not be found.

This code does not work:

(function(){
    var self = this;

    $("p").each(function(){
        $(this).click(self.myFunction);
    });

    self.myFunction = function(){ alert("myFunction"); }
})();​

When I wrap the click handler assignment in a function it does work:

(function(){
    var self = this;

    $("p").each(function(){
        $(this).click(function(){ self.myFunction(); });
    });

    self.myFunction = function(){ alert("myFunction"); }
})();

Question: Why doesn't $(this).click(self.myFunction) work, but $(this).click(function(){ self.myFunction(); }) does?


Edit: The following code does work:

$("p").click(myFunction);
function myFunction(){ alert("myFunction"); }

Shouldn't this fail as well?


P.S. I got my object working without the need to wrap the function by moving the location of the function:

(function(){
    var self = this;

    self.myFunction = function(){ alert("myFunction"); }

    $("p").each(function(){
        $(this).click(self.myFunction);
    });
})();

I guess the problem is parser related.

2
  • 1
    You need to understand javascript code parsing and evaluation order. See this: stackoverflow.com/questions/3887408/… Commented Sep 7, 2012 at 9:36
  • @slebetman +1 for you answer to the other question. Thanks. Commented Sep 8, 2012 at 8:34

2 Answers 2

3

In this:

(function(){
    var self = this;

    $("p").each(function(){
        $(this).click(self.myFunction);
    });

    self.myFunction = function(){ alert("myFunction"); }
})();?

The reference is evaluated immediately, and since nothing has been placed in self yet, it fails.

Here:

(function(){
    var self = this;

    $("p").each(function(){
        $(this).click(function(){ self.myFunction(); });
    });

    self.myFunction = function(){ alert("myFunction"); }
})();

The reference is evaluated when the click actually happens, much after self.myfunction is assigned to.

This is in fact not a problem, and an intentional design feature.

In this example:

$("p").click(myFunction);
function myFunction(){ alert("myFunction"); }

The function name is being hoisted to the top of the scope. Since there is nothing dynamic about this function definition (meaning it's not being assigned to an object dynamically), it's available all throughout this scope, from top to bottom.

Functions fill many gaps in JavaScript.

They act as lambdas, modules, methods, functions and probably more that I can't think of right now.

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

2 Comments

Good explanation, will vote up tomorrow as I have used up all my votes for the day :) This is an additional resource to understand these kinds of things, (by John Resig!): ejohn.org/apps/learn
Thanks for explaining. I need to keep this in mind when designing objects.
0

I think you already figured out your problem. At the moment you attach the handlers, self.myFunction isn't defined, so no even handler is attached.

But when you wrap the call like function(){ self.myFunction(); }, then self.myFunction is called at the moment the handler is called, not when it's attached.

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.