Functions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.
The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:
function foo(doBar)
{
function bar()
{
console.log( 'bar' );
}
function baz()
{
console.log( 'baz' );
}
window.baz = baz;
if ( doBar ) bar();
}
In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.
as a different example:
function Fizz(qux)
{
this.buzz = function(){
console.log( qux );
};
}
The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:
const obj = new Fizz();
obj.buzz();
or more concisely (if you don't need to keep the object after calling buzz):
new Fizz().buzz();
Answer from zzzzBov on Stack OverflowFunctions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.
The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:
function foo(doBar)
{
function bar()
{
console.log( 'bar' );
}
function baz()
{
console.log( 'baz' );
}
window.baz = baz;
if ( doBar ) bar();
}
In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.
as a different example:
function Fizz(qux)
{
this.buzz = function(){
console.log( qux );
};
}
The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:
const obj = new Fizz();
obj.buzz();
or more concisely (if you don't need to keep the object after calling buzz):
new Fizz().buzz();
It is called closure.
Basically, the function defined within other function is accessible only within this function. But may be passed as a result and then this result may be called.
It is a very powerful feature. You can see more explanation here:
javascript_closures_for_dummies.html mirror on Archive.org
Hey peeps,
I've been using js for a while now, but it only occurred to me recently that I should probably check that one of my habits isn't horrendously bad form or causing me memory/efficiency problems etc.
SO, here's the dilemma :
function setupExample(){
var button1 = document.getElementById("button1");
var button2 = document.getElementById("button2");
var button3 = document.getElementById("button3");
button1.addEventListener("click", toggleExampleOne);
button2.addEventListener("click", toggleExampleTwo);
button3.addEventListener("click", toggleExampleThree);
function toggleExampleOne(){
button1.classList.toggle("activated");
}//END toggleExampleOne
function toggleExampleTwo(event){
event.srcElement.classList.toggle("activated");
}//END toggleExampleTwo
}//END setupExample
function toggleExampleThree(event){
event.srcElement.classList.toggle("activated")
}//END toggleExampleThreeNow, I use a structure like this quite regularly - I tend to use example 1 in this case - but my concern now is that by referencing values outside the function called by the click event, the entirety of 'setupExample' would be kept in memory when all I actually need is the toggle functions!
Are example 2 or 3 better in this case, or am I worrying about nothing and there is absolutely no difference between the three?
Thanks in advance, peeps!
-P
Why do you think that nesting functions is bad form? Modern Javascript is often written in a class-like block structure, to make for ease of exporting.
As other commenters have observed, nested functions are "private" in the sense that you won't be able to access them directly. This is a feature, not a bug. It's really the cornerstone of object-oriented programming: by nesting related functions into the same shared block structure, you can vastly reduce the complexity of your code base.
This is the way I write JS code by default:
var basketModule = (function () {
// privates
var basket = [];
function doSomethingPrivate() {
//...
}
function doSomethingElsePrivate() {
//...
}
// Return an object exposed to the public
return {
// Add items to our basket
addItem: function( values ) {
basket.push(values);
},
// Get the count of items in the basket
getItemCount: function () {
return basket.length;
},
// Public alias to a private function
doSomething: doSomethingPrivate,
// Get the total value of items in the basket
getTotal: function () {
var q = this.getItemCount(),
p = 0;
while (q--) {
p += basket[q].price;
}
return p;
}
};
})();
This is similar to what in other languages is called a class.
What you're doing here is utilizing closures.
function toggleExampleOne(){
button1.classList.toggle("activated");
}//END toggleExampleOne
This is closing over the variable button1 in the outer scope. This will cause the function to be evaluated with this context every time it is called, which can be inefficient. There's a process you can do called lifting which flattens the closure - this is what your example three does.
However, I would largely not be too concerned about inefficiencies here. Micro-optimizations can quickly consume you: do what works best for making a maintainable application, then if you have performance problems, measure, and optimize your hot paths (the parts of your application that are used the most often). Especially so since most javascript engines are really quite optimized and will know how to transform your code in subtle ways to improve performance (like doing that lifting for you).
If you're worrying about cluttering up your global namespace though, look into modules or namespaces.
I'm generally in favor of nested functions, especially in JavaScript.
- In JavaScript, the only way to limit a function's visibility is by nesting it inside another function.
- The helper function is a private implementation detail. Putting it at the same scope is akin to making a class' private functions public.
- If it turns out to be of more general use, it's easy to move out, because you can be confident the helper is currently only used by that one function. In other words, it makes your code more cohesive.
- You can often eliminate parameters, which makes the function signature and implementation less verbose. This is not the same thing as making variables global. It's more like using a class member in a private method.
- You can give the helper functions better, simpler names, without worrying about conflicts.
- The helper function is easier to find. Yes, there are tools that can help you. It's still easier to just move your eyes up the screen a bit.
- Code naturally forms a sort of tree of abstraction: a few general functions at the root, branching out into several implementation details. If you use an editor with function folding/collapsing, nesting creates a hierarchy of closely-related functions at the same level of abstraction. That makes it very easy to study the code at the level you need and hide the details.
I think a lot of opposition comes from the fact that most programmers were either brought up in a C/C++/Java tradition, or were taught by someone else who was. Nested functions don't look natural because we weren't exposed to them much when we were learning to program. That doesn't mean they aren't useful.
You should put it at global scope, for several reasons.
Nesting a helper function into the caller increases the length of the caller. Function length is almost always a negative indicator; short functions are easier to understand, to memorize, to debug and to maintain.
If the helper function has a sensible name, reading that name is enough without needing to see the definition nearby. If you do need to see the helper definition in order to understand the caller function, then that caller is doing too much, or is working on too many levels of abstraction simultaneously.
Having the helper globally available allows other functions to call it if it turns it to be generally useful after all. If the helper isn't available, you're tempted to cut and paste it, or to forget it and reimplement it, poorly, or to make another function longer than it has to be.
Nesting the helper function increases the temptation to use variables from the caller's scope without declaration, so that it becomes unclear what the inputs and outputs of the helper are. If a function doesn't clearly state what data it operates on and what effects it has, it is usually a sign of unclear responsibilities. Declaring the helper ass a standalone function forces you to know just what it actually does.
Edit
That turned out to be a more controversial question than I thought. To clarify:
In JavaScript, big file-spanning functions often fulfill the role of classes because the language doesn't provide any other scope-limiting mechanism. Certainly helper functions should go inside such quasi-classes, not outside them.
And the point about easier reuse presupposes that if a subroutine does become more widely used, you are willing to move it out of place altogether and put it in appropriate place, e.g. a string utility library or into your global configuration registry. If you don't want to order your code like that, then you might as well nest the subroutine, just like you would do with a normal Method Object in a more "blocky" language.