loops, timeouts and callback functions in Javascript and node.js - From http://blog.mixu.net/2011/02/03/javascript-node-js-and-for-loops/
What does this code print out? Assume that console.log logs to the console.
console.log('For loop');
for(var i = 0; i < 5; i++) {
console.log(i);
}
0, 1, 2, 3, 4 - easy, right? What about this code?
console.log('setTimeout');
for(var i = 0; i < 5; i++) {
setTimeout(function() {console.log('st:'+i)}, 0);
}
The result is 5, 5, 5, 5, 5.What about this?
function wrap(callback) {
callback();
}
console.log('Simple wrap');
for(var i = 0; i < 5; i++) {
wrap(function() {console.log(i)});
}
0, 1, 2, 3, 4 -- right? (Yup.) And this?
function sleep(callback) {
var now = new Date().getTime();
while(new Date().getTime() < now + 1000) {
// do nothing
}
callback();
}
console.log('Sleep');
for(var i = 0; i < 5; i++) {
sleep(function() {console.log(i)});
}
0, 1, 2, 3, 4. And this?
console.log('nextTick');
for(var i = 0; i < 5; i++) {
process.nextTick(function() {console.log('nt:'+i)});
}
Well... it's 5, 5, 5, 5, 5.
var data = [];
for (var i = 0; i < 5; i++) {
data[i] = function foo() {
alert(i);
};
}
data0; data1; data2; data3; data4;
Again, 5, 5, 5, 5, 5.
console.log('new scope nexttick with value binding in new func scope');
for(var i = 0; i < 5; i++) {
(function() {
var j = i;
process.nextTick(function() {console.log('nexttick-new-scope-new-bind:'+j)});
})();
}
Resulting in 0, 1, 2, 3, 4. Accessing j returns the value of i at the time when the closure was executed - and as you can see, we are immediately executing the function by appending ();
console.log('new scope');
for(var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {console.log('st2:'+i)}, 0);
})(i);
}
Resulting in 0, 1, 2, 3, 4.
console.log('new scope nexttick');
for(var i = 0; i < 5; i++) {
(function() {
process.nextTick(function() {console.log('nexttick-new-scope:'+i)});
})();
}
5, 5, 5, 5, 5 - since i still refers to the old scope. Compare that with experiment #7, where while the inner code is the same, we actually establish a new variable in the wrapping closure's scope, which is then referred to by the inner code.