The following alerts 2
every time.
function timer() { for (var i = 0; i < 3; ++i) { var j = i; setTimeout(function () { alert(j); }, 1000); } } timer();
Shouldn't var j = i;
set the j
into the individual scope of the setTimeout?
Whereas if I do this:
function timer() { for (var i = 0; i < 3; ++i) { (function (j) { setTimeout(function () { alert(j); }, 1000); })(i); } } timer();
It alerts 0
, 1
, 2
like it should.
Is there something I am missing?
Scope in JavaScript refers to the current context of code, which determines the accessibility of variables to JavaScript. The two types of scope are local and global: Global variables are those declared outside of a block. Local variables are those declared inside of a block.
JavaScript has 3 types of scope: Block scope. Function scope. Global scope.
The static structure of a program determines the variable scope. The scope of a variable is defined by its location within the source code, and nested functions have access to variables declared in their outer scope.
The scope of a variable is controlled by the location of the variable declaration, and defines the part of the program where a particular variable is accessible. JavaScript has two scopes - global and local.
Javascript has function scope. This means that
for(...) { var j = i; }
is equivalent to
var j; for(...) { j = i; }
In fact, this is how Javascript compilers will actually treat this code. And, of course, this causes your little "trick" to fail, because j
will be incremented before the function in setTimeout
gets called, i.e. j
now doesn't really do anything different than i
, it's just an alias with the same scope.
If Javascript were to have block scope, your trick would work, because j
would be a new variable within every iteration.
What you need to do is create a new scope:
for(var i = ...) { (function (j) { // you can safely use j here now setTimeout(...); })(i); }
The alternative the the IIFE is a function factory:
function timer() { for (var i = 0; i < 3; ++i) { setTimeout(createTimerCallback(i), 1000); } } function createTimerCallback(i) { return function() { alert(i); }; } timer();
This being said, this is one of the most asked questions in the javascript tag. See:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With