-1

I've searched around, and I know there are tons of duplicate questions about solving this problem, but I know how to solve the problem and am not asking about that. I'm trying to better understand WHY this happens. I'm trying to understand based off of this explanation

var elems = document.getElementsByClassName("myClass"), i;

for (i = 0; i < elems.length; i++) {
    elems[i].addEventListener("click", function () {
        "use strict";
        this.innerHTML = i;
    });
}

I'm confused about how each functions retains a reference to the same copy of i because i is a number, which isn't passed around by reference, right? For example:

> a = 1
1
> b = a
1
> a = 2
2
> b
1

That being the case, I don't understand why each function is given a reference to a number since, unless I'm mistaken, numbers aren't passed around by reference. I've read explanations of this in several places but none of them have been able click for me or give me one of those 'Aha!' moments, so any help is much appreciated.

Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
carc
  • 63
  • 2
  • 8
  • 1
    This hsa nothing to do with references, it's a scoping issue. – simonzack Dec 18 '14 at 21:05
  • 1
    possible duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – simonzack Dec 18 '14 at 21:05
  • I looked at that, and similar questions on SO. The problem is that I still didn't quite grasp it, and I can't ask my own questions or anything on those threads (not enough rep to leave comments, the only place that seemed OK for me to ask my own clarifying questions). If there is a more appropriate way to ask for further clarification on already existing questions, I'd love to know. – carc Dec 18 '14 at 21:20
  • carc - you might try the chat rooms or an irc channel. I don't use them myself but it seems appropriate. – Kenan Banks Dec 18 '14 at 21:24
  • Thanks, I'll try that next time I'm in a similar situation – carc Dec 18 '14 at 21:43

2 Answers2

1

The problem has nothing to do with pass-by-value or pass-by-reference.

The variable i in the linked page is rebound to a new value each iteration of the loop. However, every function is referencing the single outer variable, i. Since none of these functions will actually run until after the loop has completed, they will all point to the final value of i.

If you were actually executing those functions as soon as you created them, things would work closer to how you expect.

Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
  • I thought variables that lived outside of a function at the time of declaration were encapsulated inside that function's scope? Essentially as if they were local variables of that function and were defined with whatever value they had at the time of declaration? Is that not right? – carc Dec 18 '14 at 21:21
  • 1
    time to mention "closures" – Igor Dec 18 '14 at 21:24
  • 1
    After playing around more with this in code, I realize that I'm being kind of an idiot and that I use this to my advantage in my own code all the time whenever I essentially use private variables in a module. Can't believe it didn't click for me that it was the same thing until now. Thanks, I had my "aha" moment (even if it is a bit embarassing). I think the term "referencing the same copy of i" in all the other answers is what threw me off - it kept making me think pass-by-reference. – carc Dec 18 '14 at 21:41
  • Yes carc - this is your happenstance introduction to Javascript closures, which means that all the code inside a function has access to the variables defined _outside_ that function's scope. – Kenan Banks Dec 19 '14 at 13:43
1

I know it's been answered but here's an example of how to solve this problem real quick. Wrap it up in a function and you solve that scope problem.

var elems = document.getElementsByClassName("myClass"), i;

for (i = 0; i < elems.length; i++) {
    (function(i){
        elems[i].addEventListener("click", function () {
            "use strict";
            this.innerHTML = i;
        });
    })(i)
}
Shawn Whinnery
  • 3,519
  • 3
  • 16
  • 16