How does Javascript39s Scope work getting unexpected behavior

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

Heres a sample bit of code, similar to that that gave me grief:

for(var i=0;i<3;i++){
    var Proof = true
    if (i == 0){
        Proof = false
        //var CallBack = function(){alert(Proof);}; // true????
        var CallBack = function(){alert(i);};
    }
}

// Whatever happened to local scope? shouldn t CallBack be undefined now?
CallBack()// alert(3), should be 0?

CallBack isn t undefined, it alerts true or 3, could someone please explain to me what is going on that is making it act like this? is there some local keyword I am missing, or does JS not have scope? I am using no framework, and would appreciate some help on how to sort this out, and do this kind of thing properly...

Answers

JavaScript doesn t have block scope at all (yet, see below). All variables are declared throughout the function in which they appear (or throughout the global scope, if they re at global scope).

Assuming the code you ve quoted is the only code in its scope, it s exactly the same as this:

var i;
var Proof;
var Callback;

for(i=0;i<3;i++){
    Proof = true
    if (i == 0){
        Proof = false
        //CallBack = function(){alert(Proof);}; // true????
        CallBack = function(){alert(i);};
    }
}

// Whatever happened to local scope? shouldn t CallBack be undefined now?
CallBack()// alert(3), should be 0?

http://blog.niftysnippets.org/2008/03/poor-misunderstood-var.html http://blog.niftysnippets.org/2008/03/poor-misunderstood-var.html


CallBack()// alert(3), should be 0?

No, 3 is correct, because that s the value of i as of when CallBack is called . CallBack is a closure over the context in which it was created. It has an enduring reference to the context (including the i variable), not a copy of what existed when it was created.

If you wanted to get 0 instead, you d have to have CallBack close over something other than i, something that won t change. The typical way to do that is to use a builder function you pass a value into:

function buildCallBack(index) {
    return function() { alert(index); };
}

Then:

CallBack = buildCallBack(i);

The value of i is passed into buildCallBack as the argument index. buildCallBack creates a function closing over the context of that call to buildCallBack and using that index argument. Since that argument s value is never changed, the callback alerts 0 (in this case) rather than 3.

http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html


http://wiki.ecmascript.org/doku.php?id=harmony%3ablock_scoped_bindings http://wiki.ecmascript.org/doku.php?id=harmony%3ablock_scoped_bindings

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/20990661/how-does-javascripts-scope-work-getting-unexpected-behavior

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils