I was working today at a front-end Javascript project. I will try to keep the description of the problem and the solution as short as possible.
I had to add click handlers to the links on a page that redirect the user to other pages, so I had 2 Javascript array arrayOfRedirectLinks and pageLinkElements:
var arrayOfRedirectLinks, pageLinkElements;
Initially I wrote the addEventHandlers function like this:
var addEventHandlers = function() {
    var i, link;
    for( var i in arrayOfRedirectLinks) {
        link = arrayOfRedirectLinks[i];
        pageLinkElements[i].addEventListener('click', function(e) {
            e.preventDefault();
            window.location = link;
        });
    }
}
I thought that this solution will do the job until... well until I opened the browser, clicked several links and noticed that all of them redirected me to the same link (the last link in the arrayOfRedirectLinks).
Finally I found that my problem was similar to the one posted here Javascript multiple dynamic addEventListener created in for loop - passing parameters not working
And indeed both the first and the second solution posted there worked for me
var addEventHandlers = function() {
    var i, link;
    for( var i in arrayOfRedirectLinks) {
        (function(link){
        link = arrayOfRedirectLinks[i];
        pageLinkElements[i].addEventListener('click', function(e) {
            e.preventDefault();
            window.location = link;
        });
        }(link));
    }
}
and
var passLink = function(link) {
    return  function(e) {
               e.preventDefault();
               window.location = link;
            };
};
var addEventHandlers = function() {
    var i, link;
    for( var i in arrayOfRedirectLinks) {
        link = arrayOfRedirectLinks[i];
        pageLinkElements[i].addEventListener('click',passLink(link));
    }
}
Now this seems to work but I don't understand why it works. I came with the following explanation and I would like if someone can confirm if it's correct:
- When I declare a function in Javascript, it gets the references to the variables in the scope of the function where it was declared. ( i.e. my event handler gets a reference to the - linkvariable in the- addEventHandlersfunction)
- Because the handler gets a reference to the variable - link. When I reassign a value to the- linkvariable, the value that will be used when the click handler gets triggered will also change. So the- linkvariable from the event handler is not simply copy with of the- linkwith a different memory address and same value as when the function handler was added, but they both share the same memory address and therefore the same value.
- Because of the reasons described at 2), the all the click handlers will use the redirect to the same - link, the last- linkin the array- arrayOfRedirectLinksbecause that's the last value that will get assigned to the- linkvariable at the end of the- forloop.
- But when I pass the - linkvariable as a parameter to another function, a new scope it's created and the- linkinside that scope actually shares only it's initial value with the value of the- linkparameter passed to the function. The references of the 2- linkvariables are different.
- Because of 4), when I pass the - linkto the click handler, it will take the reference to the- linkvariable in the Immediately Invoked Function Expression who itself doesn't share the same address with the- linkin the- addEventHandlersfunction. Therefore each- linkfrom the event handler functions will be isolated from the others and will keep the value of the- arrayOfRedirectLinks[i]
Is this correct?
 
     
    