0

For easier explanation, please see the corresponding jsFiddle

This is the code I'm calling in a loop:

var eventNames = ["click", "dblclick", "contextmenu"];
for (var i = 0; i < eventNames.length; ++i) {
    var crtName = eventNames[i];
    $("#" + crtName).click(function () {
        alert("Event " + crtName);
    });
}

Sure, when the handler is called, crtName is always "contextmenu" because at this point, the for-loop has ended and i is always pointing to the highest possible value.

Note: In the current example, I'm using the click function from jQuery. In my real application, there's another framework being called to register an event handler. So this is just an example and it cannot be changed. Neither can I add parameters being passed to the handler when the event occurs. Therefore it's not a jQuery question.

As well, it's similar to the question "need help understanding JS code", except for the important fact that I'm not calling my event handler myself!

Basically: I would like the variable crtName to be populated when the handler is being registered, not when it's called.

0

3 Answers 3

2

Issue:

JavaScript's scopes are function-level, not block-level, and creating a closure just means that the enclosing scope gets added to the lexical environment of the enclosed function.

After the loop terminates, the function-level variable crtName has the value contextmenu, and that's what the inner function 'sees'.

So you can do,

var eventNames = ["click", "dblclick", "contextmenu"];

for (var i = 0; i < eventNames.length; ++i) {
    var crtName = eventNames[i];
    attach_event(crtName);
};

function attach_event(crtName) {
    $("#" + crtName).click(function () {
        alert("Event " + crtName);
    });
}

Read More about closures:

  1. Javascript infamous Loop issue?
  2. Javascript closure insideloops - simple practical example
  3. How do JavaScript closures work?

Fiddle

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

1 Comment

@djay please check updated ans with references given
0

As Pilot said, you need to use a closure, like this:

(function (crtName) {
    $("#" + crtName).click(function () {
        alert("Event " + crtName);
    });
})(crtName);

This way, you pass crtName to a self invoking function that gets executed with the right event name for each member of the array

Comments

-1

Since you are using crtName to refer to the element's ID, just reference this.id inside the event handler

2 Comments

thanks for your message. As written in the example, the jQuery-way is only used to simplify the example code and to create a runnable jsFiddle. Therefore, this isn't a solution. =(
If you're using the variable to set the type of event, consider also using evt.type to get the event type.

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.