Scoping anonymous functions
This is obviously a no-brainer in that knowing something like this works in JavaScript, but it never really occurred to me to even do such a thing until today. Take the following example which ‘calls’ the anonymous function within a unique scope:
Scoping anonymous funcitons
var o = 'hello world';
(function() {
alert(this);
}).call(o);
It seems ridiculous (in a good way), but it works!
So what’s this mean?
It’s actually a big deal. Think about how many times you’ve lost your desired scope due to being inside the scope of another function. Confused? How many times have you done the following:
Pitfalls anonymous functions
// timeout functions
function Constructor() {
this.foo = 'bar';
var that = this;
this.timerId = window.setTimeout(function() {
alert(that.foo);
}, 10000);
}
// local functions
Constructor.prototype.getFoo = function() {
var that = this;
var getInternalFoo = function() {
return DED.isString(that.foo) ? that.foo : 'new foo';
}();
};
Ok, still not a huge deal, but we can clean up the code a bit, and I would sway from using this on non-anonymous functions where scope should be explicitly defined by the author. Here’s how we can rewrite the code above without using the silly old this = that convention.
Rewritten with proper scope
// local functions
Constructor.prototype.getFoo = function() {
var getInternalFoo = function() {
return (DED.isString(this.foo) ? this.foo : 'new foo';
}.call(this);
};
Ok, what about function callbacks that need scope inducing
(Hehe. Scope inducing, that sounds funny… (anyway)) As you noticed above in the first example with the setTimeout, the first argument takes in a function callback which is different than simply immediately invoking a function. Funny enough, the work around for this is to…. (yeah you guessed it), add another closure! Note the two following snippets of code. The first immediately executes and alerts “hello world”, the second waits for five seconds, and does likewise:
Scoping it up
var o = 'hello world';
// first snippet
(function() {
alert(this);
}).call(o);
// second snippet
window.setTimeout(function() {
(function() {
alert(this);
}).call(o);
}, 5000);
Pretty fun, huh? Yeah, I thought so too. Cheers.













May 6th, 2008 at 12:51 pm
While I agree that this is pretty cool, I’m not sure I prefer it to the that = this convention. Seems like more code to me and something that will definitely confuse a novice JS programmer (not that the that = this convention wouldn’t).
May 6th, 2008 at 1:35 pm
I think there is either an extra paren before DED, or a missing paren before the ;.
return (DED.isString(this.foo) ? this.foo : ‘new foo’;
Always happy to see JavaScript another excellent JavaScript writeup, great stuff!
May 6th, 2008 at 1:59 pm
thanks for the small catch. It’s corrected.
May 6th, 2008 at 2:03 pm
Ooo… nice trick.
May 6th, 2008 at 2:42 pm
Wow. I’ve just finished writing some tutorials on this stuff (about 5 mins ago!) and up pops this great example. Nice.
May 6th, 2008 at 3:05 pm
heh, I was playing with this idea yesterday, Function.apply() and Function.call() are very nice.
May 6th, 2008 at 8:20 pm
@John: Go figure :) Suppose there was a movement in the JavaScript zen force?
@Bryon: Indeed, they’re pretty rad.
May 6th, 2008 at 11:49 pm
[…] Javascript function scoping trick from Dustin Diaz, master of cool Javascript tricks. His Javascript Video Tutorials were the first time I was exposed […]
May 7th, 2008 at 12:44 am
I find that using a bind function for scope inducing is both short and clear in its purpose:
window.setTimeout(function() {alert(this);
}.bind(o), 5000);
It’s also noob friendly in that the abstraction works quite well and they don’t have to know about the implementation:
Function.prototype.bind = function(o){var fn = this;
return function(){
return fn.apply(o, arguments);
};
};
May 7th, 2008 at 5:10 am
@Tore: Though I like the usage of bind, I believe Dustin was trying to move away from the that = this convention (which is really what bind is doing).
@Dustin: Great writeup. This made a light go off for me and brought visions of multiple code segments that can be cleaned up as a result. Thanks.
Also, didn’t you mean “the silly old that = this convention” instead of “the silly old this = that convention”. Not nitpicking, just thought you’d want to know.
May 7th, 2008 at 11:49 am
What are “funcitons”? :P
May 7th, 2008 at 12:48 pm
I do like that solution, Tore.
Although I would call the function “scope” instead of “bind”. I think “bind” is commonly used for adding event listeners to elements.
May 7th, 2008 at 1:49 pm
@leville: Haha. Yes, I did flip those accidentally :) My bad. But ya’ll know what I meant.
May 8th, 2008 at 12:23 am
“obviously a no-brainer”? Wow, I think it is brilliant. Good work Dustin, I am going to use it right now!