views:

128

answers:

3

In the question

http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem

the accepted answer from Christoph's says

JavaScript's scopes are function-level, not block-level

What if Javascript's scopes are block-level, then would the Infamous Loop problem still occur? Or will there be a different (and easier) way of fixing it?

Is it as opposed to other languages, where using a { would start a new scope?

A: 

Basically, it's a way of saying the value obtained via the first setup is a 'pointer' - a reference to the value of the variable when the method is invoked. In the second instance, the value is a 'copy', not a 'pointer', so each instance has it's own value.

That's assuming I have read your question right.

Tejs
+1  A: 

If blocks created scopes (for closures), then this would work the way people who later post a question on StackOverflow think it might work:

for (var i = 0; i < thing.length; ++i) {
  var element = $('#elem' + i); // making this up randomly here
  setTimeout(function() { doSomething(element); }, 100);
}

That would work because each iteration of the loop body would (probably) create a new scope, and thus a new "element". As it is, the fact that no new scope is created means that each function instantiated through the progress of the loop shares the same "element" variable, and thus the code doesn't work properly and another StackOverflow javascript question is born.

Pointy
+1  A: 

I found an answer:

Javascript 1.7 and above supports block-level scope, and Firefox 3.0 and above supports it. (See http://en.wikipedia.org/wiki/Javascript#Versions )

I tried the following code using Firefox 3.5.9:
Note that the keyword let is used, which will create a block-level scope.

<a href="#" id="link1">ha link 1</a>
<a href="#" id="link2">ha link 2</a>
<a href="#" id="link3">ha link 3</a>
<a href="#" id="link4">ha link 4</a>
<a href="#" id="link5">ha link 5</a>


<script type="application/javascript;version=1.7"/>  

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

</script>

Sure enough, a new scope is created, with a new x in it. The anonymous function that does the alert(x) captures this scope (the whole scope chain) and remembers it, thus forming the closure. When this anonymous function is invoked, the scope is there, and when it looks for x, sure enough, the x is in that scope as 1, 2, 3, 4, 5 respectively. Try and change the let into a var and you get the infamous old problem again, because no new scope is created.

動靜能量