In Javascript, a function starts a new scope, but we have to be careful that this function is called so that a scope is created.

In Javascript, I sometimes get too caught up in the idea that a function creates a new scope, that sometimes I even think that the following anonymous function will create a new scope when it is defined and assigned onclick:

<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="text/javascript">

    for (i = 1; i <= 5; i++) {

        document.getElementById('link' + i).onclick = function() { var x = i; alert(x); return false; }
    }

</script>

      

but in fact the anonymous function will create a new scope, that's correct, but ONLY when it is called, is it? So x

no new scope is created inside the anonymous function. When the function was called later, there is a new area in order, but i

in the outer area, and x

gets its value, and still doesn't care.

The following code will actually call the function and create a new scope, and why x

is it a new local variable x

in a new scope every time and calling the function when the on link is clicked will use different x

in different scopes.

<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="text/javascript">

    for (i = 1; i <= 5; i++) {

        (function() {
            var x = i;
            document.getElementById('link' + i).onclick = function() { alert(x); return false; }
        })();  // invoking it now!
    }

</script>

      

If we move var

before x

, then it is global x

, and therefore no local variable will be created in the new scope x

, and hence clicking on the links will still get the same number that is the value of the global x

.

Update: Question: We have to be careful when parsing the code so that the function does not create a scope when it is simply defined and assigned. It must be called. This is true?

+2


a source to share


3 answers


The scope of a function is set when a function object is created for example:

var fn;
// augment scope chain:
with ({foo: "bar"}) {
  fn = function () { // create function
    return foo;
  };
}​​
// restored scope chain
fn(); // "bar"

      

In the example above, a function is created inside a block with

, there the current scope is expanded to inject an object with a property foo

in the scope chain.



In your second example, the same thing happens, the handler function onclick

is created inside an anonymous auto-call function that itself created a new lexical scope.

At the moment when this function is automatically called at each iteration of the loop, the value is i

written to this area in a variable x

, then a handler function is created inside this area onclick

, and it can solve the problem.

+1


a source


You're right, but you're also confusing. Instead of thinking of functions as simply "creating a new realm," understand what's really going on. Javascript interprets the variable by traversing the scope chain. If the variable is not in the function scope, it will hoist to the enclosing level in case of a close. This part happens during the interpretation of the variable. The scope itself is created when the function is there, but where you get confused, nothing is "captured" in the scope at the time. It just enlarges the chain of regions.



Why setting closures in loops is so "out of the box" in javascript programming - you are right to enable the automatic execution of an anonymous function if you want to capture a value i

during a function declaration.People tend to think (especially in procedural languages) that external the volume is frozen and all current values ​​are passed to the new function area, which is not the case.

+2


a source


I do not understand your question, but I do not see anything strange or wrong in this.

In the first case, a closure is created, and when the event is called, it creates its own scope and retrieves the value from the self in its outer scope maintained by the closure. But this code has already been executed so that i = 6, because the loop is long, and therefore x = 6.

In the last example it is the same, you create a closure, and when the event is called, it will retrieve x from its outer scope backed by the closure, but it has already been executed, and since it started immediately into a loop, this time x is i at time execute the function (to create a closure).

0


a source







All Articles