Skip to main content
Ben Nadel at TechCrunch Disrupt (New York, NY) with: Aaron Foss and Mark C. Webster
Ben Nadel at TechCrunch Disrupt (New York, NY) with: Aaron Foss ( @aaronfoss ) Mark C. Webster ( @markcwebster )

Using Named Functions Within Self-Executing Function Blocks In Javascript

By on

This is just a quick tip that I recently picked up from watching Paul Irish discuss 10 things that he learned from the jQuery source code. It was a couple of weeks ago, but I don't believe that this tip was actually something in the jQuery source code; rather, I believe it was just something that he demonstrated in one of his explantations. Anyway, what he showed me was that you could use named functions in self-executing function blocks.

Typically, when we we create a self-executing function block, we do so with an anonymous (lambda) function:

( function(){ .... function body .... } )();

This works great - it takes the anonymous function and executes it immediately. As Paul demonstrated, however, the same thing can be done with a named function:

( function myFunction(){ .... function body .... } )();

While this additional variable reference - myFunction - is not always needed, it does provide us with a way to create recursive, self-executing functions. In the following demo, I've created a self-executing function that increments a counter, logs it, and then calls itself recursively:

<!DOCTYPE html>
<html>
<head>
	<title>Named Self-Executing Functions</title>
	<script type="text/javascript">

		// Define a variable to be accessed within the
		// self-executing function block.
		var counter = 0;

		// Create a self-executing function block; however, rather
		// than passing in an anonymous, headless function, let's
		// pass in a named function.
		(function useCounter(){

			// Increment and log counter.
			console.log( ++counter );

			// Call *this* function again in after a short timeout.
			// Since it has a name, we don't have to use the
			// depracated arguments.callee property.
			setTimeout( useCounter, 1000 );

		})(); // Self-execute.

	</script>
</head>
<body>
	<!-- Intentionally left blank. -->
</body>
</html>

As you can see here, we have defined the function, useCounter(), as the target of the self-executing function block. The logic, within this self-executing function, then executes the useCounter() function recursively after a brief timeout. After letting this page run for a few seconds, I get the following console output:

1
2
3
4
5

As you can see, the self-executing behavior of the function block is exactly the same; but, we gain the added benefit of being able to reference the function in question without having to rely on deprecated features such as "arguments.callee." A small but awesome tip from Paul.

Want to use code from this post? Check out the license.

Reader Comments

8 Comments

This approach is pretty great - I'm a fan.

I picked it up from this gist from Ben Alman (which itself was forked from a gist from Remy Sharp), which shows some other ways to use this technique (such as waiting before the first execution or using setInterval instead of setTimeout).

Also, given that you're using the HTML5 doctype, you can drop the type attribute from the script tag. It felt weird at first, but I'm enjoying not having to bother with that now. :)

1 Comments

Naming your anonymous functions is also nice because those names show up in stack traces when you debug in tools like Firebug. Seeing descriptive names there makes a world of difference when you're debugging something a few callbacks deep.

15,663 Comments

@Liam,

Hmmm. I might be missing something, but I cannot get that to work for me. When I do this:

var foo = (function(){ alert( "bar" ); })();
foo();

... only the initial alert() works; the second one errors out that "foo" is undefined.

Typically, when I need to get "a" callback from the self-executing function, I need to explicitly return it:

var foo = (function(){ return( ..fn.. ); })();

... am I missing something?

@Brian,

Thanks for the link. Ben Alman definitely has a lot of great stuff! I'll be sure to check out the gist. As far as removing the "type" attribute from the Script tag, the only reason I want to shy away from that is that I actually use Script tags for other types as well (ex. type="text/template").

@Dave,

Oh cool - I hadn't even thought of that.

@Hal,

My pleasure - always happy to pass on some good stuff I get from others.

@All - a quick follow up on the concept in the context of method callbacks:

www.bennadel.com/blog/1989-Using-Named-Callback-Functions-In-Javascript-Methods.htm

4 Comments

@Ben: forgot to mention that it needs to be inside an object. I tend to keep all my functions inside of a global object.

obj = {};
obj.funcName = (function(){ alert('hi'); })();

1 Comments

hi Ben,

(
function s()
{
alert("moh");
}
)();
s();

this code do well in IE,
but doesn't work in my FireFox 3.6.8 and my opera 10

in FF it says 's' is defined in last line of the code above.

is it my fault? or something problem with the browsers.

15,663 Comments

@Mohsen,

This is my experience as well. I think the self-executing block creates a kind of self-contained scope. You could probably do something like this:

var s = (function s(){ .... return(s); })();

The "return(s);" should return the local "s" reference to the calling scope, variable.

22 Comments

This will work as you expect since the "calling" scope for the self-executing anonymous function is the global scope:

var foo = null;
(foo = function(){ alert( "bar" ); })();
foo();

22 Comments

Just to confirm your answer about 's' is correct where the self-invoking function s has its own scope and is passed back to the global scope var s. This will also alert 's' twice as you expected:

var s = (function s(){alert('s'); return s;})(); s();

Self-invoking functions are best for once-off/initialization tasks so normally you would not return the function.

15,663 Comments

@Johans,

It's an interesting thing; I just read an article posted on related blog entry about the difference between function definition and function expressions. I wonder if this comes into play here?

Anyway, thanks for pointing out that a reference to the method can be assigned within the (..) expression.

1 Comments

Hiya Ben,

I just found this after a Googling 'named self-executing functions' (I had tried 'named immediately-invoked function expressions', but Cowboy's post coining that expression was the only truly relevant hit - for the record, I'm on his side ;).

I use these for the same reason you mention - ie you may want to recurse (as arguments.callee is being deprecated this reason is all the more valid) - but also, as Dave points out, because I like to name all my functions for the sake of stack tracing during debug.

Reason I Googled was because my implementation kept on getting screwed. If I might just explain the fringe case:

I don't like finishing lines with semi-colons - to my overbearing design sensibilities they make the code harder to read, and if you're bracketing and coding properly they shouldn't be necessary. Well, this can be one such case: If the previous statement isn't cut off with a semi-colon, a named immediately-invoked function expression immediately afterwards will cause a type error: previous block is not a function (or something to that extent) - even if the previous block is a function.

This doesn't happen if the function is anonymous, or if it's self-invoked by means of a preceding unary operator rather than enclosing parens. So:

/* Fine */
invocation()
(function(){}())
 
/* Fine */
invocation()
~function name(){}()
 
/* TypeError */
invocation()
(function name(){}())
 
/* Fine */
invocation();
(function name(){}())

Just thought I'd share that little tidbit with y'all in case somebody lands here with the same problem I had… ;)

1 Comments

Hi Ben,

you forgot to mention the most important thing for named self-executing functions - they can be referenced by name ONLY inside their execution context (which is parens in this case), it means to be called by name only inside itself, recursively. Exactly the case you described.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel