简体   繁体   中英

Why does one JavaScript closure work and the other doesn't?

There are two versions, supposedly when the user click the first link, it will alert "1", and the second link, "2", etc.:

Version 1:

<a href="#" id="link1">click me</a>
<a href="#" id="link2">click me</a>
<a href="#" id="link3">click me</a>
<a href="#" id="link4">click me</a>
<a href="#" id="link5">click me</a>

<script type="text/javascript">
    for (i = 1; i <= 5; i++) {
        document.getElementById('link' + i).onclick = (function() {
            return function() {
                var n = i;
                alert(n);
                return false;
            }
        })();
    }
</script>

Version 2:

<a href="#" id="link1">click me</a>
<a href="#" id="link2">click me</a>
<a href="#" id="link3">click me</a>
<a href="#" id="link4">click me</a>
<a href="#" id="link5">click me</a>

<script type="text/javascript">
    for (i = 1; i <= 5; i++) {
        document.getElementById('link' + i).onclick = (function() {
            var n = i;
            return function() {
                alert(n);
                return false;
            }
        })();
    }
</script>

Version 1 will not work. Version 2 will. I think I know the reason why, but would like to compare with other people's explanations as to why version 1 doesn't work.

Version 1 does not work because there's a common variable "i" (a global variable in this case, because you forgot var ) that is shared by every "click" handler function the loop creates.

In the second version, you create a new lexical scope with the little wrapper function. That gives each "click" handler it's very own private "i".

In the second example you create a var n = i; it makes i value scoped inside the onclick function. While at the first one the onclick function still uses global value of i

I'd suggest this usage instead:

  for (i = 1; i <= 5; i++) {
    document.getElementById('link' + i).onclick = (function(i) {
      return function() {
        alert(i); 
        return false;
      }
    })(i);
  }

In this case you'll get the same behaviour since i will be the local variable for onclick function as it's an argument.

First does not work because: i is the part of each closure. After 5 iterations now i is 6 due to postfix increment operator. Each time when event handler is invoked it gets the value of i from its closure scope that is always 6.

Second part works: because each closure makes a copy of i in n, n is part of each closure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM