setTimeout's Secret Free
Read the title how you wish, setTimeout has a secret it has been holding onto for window.Infinity milliseconds.
tl;dr: Solution 3.
The Problem
Because setTimeout is defined globally on the window object, the this binding frequently becomes an issue. Case in point:
// Goal: print 0, 1...8
for( var i = 0; i < 9; i++ ) {
setTimeout(function() {
console.log( i );
}, 0);
}
Output:

Solution 1
for( var i = 0; i < 9; i++ ) {
setTimeout(function() {
console.log( this );
}.bind( i ), 0);
// bind context
}
Output:

In this example, rather than binding a real context, we bind the only thing that matters to us--the variable i.
Now, why the weird PrimitiveValue output? You must bind to an object, not a primitive; as a result we bind to new Number( i ).*
Solution 2
for( var i = 0; i < 9; i++ ) {
setTimeout(function( val ) {
console.log( val );
}.bind( null, i ), 0);
// bind with args
}
Output:

In this example, we don't care about the context thisArg at all. Whatever is passed into bind after the thisArg becomes a parameter (val), which is fed into the anonymous function.
Solution 3 (Personal Fave)
for( var i = 0; i < 9; i++ ) {
setTimeout(function( val ) {
console.log( val );
}, 0, i);
// Huh? The bind is gone!
}
Output:

A solution without bind and the namesake for this post. setTimeout doesn't just take a function and milliseconds as parameters, it also takes values which it will gladly pass to the function inside:

Further Reading:
- A quick review of JavaScripts's bind function can be found here.
- Read more about
setTimeoutat MDN. - Learn the difference between
new Number( 3 )andNumber( 3 ). - More on JavaScript primitives.
*Thanks to Andrew Teich for eloquently explaining binding, or lack-thereof, to primitives.
comments powered by Disqus