1

I am more of a C++/Java programmer and fairly new to Javascript. I have been reading Javascript the good parts book.In the chapter on Functions, the author cites and example of attaching an event listener to nodes in the DOM by doing the following

     // When you click on a node, an alert box will display the ordinal of the node.

1 var add_the_handlers = function (nodes) {
2        var i;
3        for (i = 0; i < nodes.length; i += 1) {
4            nodes[i].onclick = function (i) {
5                return function (e) {
6                    alert(e);
7                };
8            }(i);
9        
10 };

The aim of the above function is to add an onclick event handler to all of the nodes in the DOM such that when anyone of the nodes is clicked it alerts the number assigned to it or its ordinal.

I am not able to understand lines 5 through 8. I understand that the function (the onclick = function(i)...) is immediately called with i as its argument. But how is this 'i' being passed to the function that is being returned ? How is 'e' getting the value of 'i' that is later being alerted?

I tried playing around with it and ran the following code in my browser

window.onclick = function(i){
    return function(e){
        console.log("Inner function called");
        alert(e);
    }
}(4); 

I expected an alert window with the number 4 in it. Instead the alert window shows [object MouseEvent].

I would really appreciate if someone explained this to me. Thanks

3 Answers 3

2

It's a mistake in the book. They were trying to demonstrate the awful (performance-wise) pattern of using an otherwise unnecessary function scope to allow an inline function to closure around a variable in an outer scope, which, because it is not referenced anywhere else, becomes a kind of private variable referenced only by the inline function. The code would do its job if the i variable was indeed used as the argument to the alert() call:

var add_the_handlers = function(nodes) {
    for (var i = 0; i < nodes.length; ++i) {
        nodes[i].onclick = function(i) {
            return function() {
                alert(i);
            };
        }(i);
    } // end for
};

add_the_handlers(document.getElementsByTagName('div'));

http://jsfiddle.net/pzht9mLu/

In the book's code, instead of closuring around the function parameter i in the outer scope, the inline function that becomes the onclick handler doesn't closure around anything. Instead, the e variable that is used as the argument in the alert() call binds to the function parameter e of the inline function (that's why no closuring happens; a closure only happens when a variable reference inside a function scope fails to bind to any local inside the scope, and instead binds to a variable in an outer scope). Because the function ends up serving as an event handler, its parameter e is set equal to the Event object that initiated the callback (if and when it happens), and that's why you see that in the alert message.

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

Comments

0

What you should realize is that in lines 5-9 (where's number 7 btw?:)) a new function is created, which will be bound as the event listener function of the onclick.

See line 9:

}(i); 

This means that the above function is immediately invoked, passing in i as its function parameter, and then it returns a new function.

Should you, for example, use the value of i in this inner function, it is captured in a closure, so the onclick function will have access to it, even though it is invoked from an entirely different scope.

Comments

0

I tried playing around with it and ran the following code in my browser

window.onclick = function(i){
    return function(e){
        console.log("Inner function called");
        alert(e);
} }(4);

I expected an alert window with the number 4 in it. Instead the alert window shows [object MouseEvent].

The argument i is never used. The alert produces e, which is the argument to the onclick event handler. Which is a MouseEvent object.

var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
    nodes[i].onclick = function (i) {
        return function (e) {
            alert(e);
        };
     }(i);
};

The aim of the above function is to add an onclick event handler to all of the nodes in the DOM such that when anyone of the nodes is clicked it alerts the number assigned to it or its ordinal.

I am not able to understand lines 5 through 8. I understand that the function (the onclick = function(i)...) is immediately called with i as its argument. But how is this 'i' being passed to the function that is being returned ? How is 'e' getting the value of 'i' that is later being alerted?

i Isn't passed to the second function, and will never be shown by your current code. What you're doing now is effectively no different than this:

nodes[i].onclick = function (e) { alert(e); };

If you want to produce an alert with the correct value of i in it, you'd simply use your original code but alert i instead of e.

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.