Reputation:
When I have some code I need to execute more than once I wrap it up in a function so I don't have to repeat myself. Sometimes in addition there's a need to execute this code initially on page load. Right now I do it this way:
function foo() {
alert('hello');
}
foo();
I would rather do it this way:
(function foo() {
alert('hello');
})();
Problem is, this will only execute on page load but if I try to call it subsequent times using foo()
it won't work.
I'm guessing this is a scope issue but is there any way to get self executing functions to work upon getting called later?
Upvotes: 15
Views: 21979
Reputation: 2308
The second function foo
is a function definition expression.
In a function definition expression, you can only call the function with the name within the function itself according to "Javascript the definitive guide":
For function definition expressions, the name is optional: if present, the name refers to the function object only within the body of the function itself.
It can be used in a recursion function definition expression.
For example:
var f = function factorial(n) {
if (n == 0 || n == 1)
return 1;
else
return n * factorial(n-1);
}
Upvotes: 2
Reputation:
If your function doesn't rely on a return value, you can do this...
var foo = (function bar() {
alert('hello');
return bar;
})(); // hello
foo(); // hello
This uses the local reference bar
in the named function expression to return the function to the outer foo
variable.
Or even if it does, you could make the return value conditional...
var foo = (function bar() {
alert('hello');
return foo ? "some other value" : bar;
})(); // hello
alert( foo() ); // hello --- some other value
or just manually assign to the variable instead of returning...
var foo;
(function bar() {
alert('hello');
foo = bar;
})(); // hello
foo(); // hello
As noted by @RobG, some versions of IE will leak the identifier into the enclosing variable scope. That identifier will reference a duplicate of the function you created. To make your NFE IE-safe(r), you can nullify that reference.
bar = null;
Just be aware that the identifier will still shadow an identifier with the same name up the scope chain. Nullifying won't help that, and local variables can not be deleted, so choose the NFE name wisely.
Upvotes: 34
Reputation: 56457
To be called from outside, the function has to be visible from outside. Ideally you would have the self executing function inject it in some passed in context (in this case, this
, which references the global context):
(function(context) {
var foo = function() {
alert('hello');
};
foo();
context.foo = foo;
})(this);
...
foo();
More interesting patterns can be found here.
Upvotes: 4
Reputation: 150010
If foo()
is intended to be a global function, i.e., a property of window
, you can do this:
(window.foo = function() {
alert('hello');
})();
// at some later time
foo();
The expression in the first set of parentheses does the assignment to create foo
, but also evaluates to be the function so you can invoke it immediately with ()
on the end.
This pattern works even if the function is supposed to return a value.
Upvotes: 5