In JavaScript, PL/SQL and some other languages, functions can be nested, i.e. declared within another function. This could be used to break a large function into smaller pieces, but keep those pieces within the context of the larger function.
function doTooMuch() {
function doSomething () {
...
}
function doSomethingElse() {
...
}
function doYetAnotherThing() {
...
}
// doTooMuch body
doSomething();
doSomethingElse();
doYetAnotherThing();
}
In some cases, when those smaller functions do not use local variables of the larger function, this could easily changed to a version where all functions are unnested.
function doSomething () {
...
}
function doSomethingElse() {
...
}
function doYetAnotherThing() {
...
}
function doTooMuch() {
doSomething();
doSomethingElse();
doYetAnotherThing();
}
Assuming that those nested functions are not to be used anywhere else, is it better to keep them within the context of the large function or is it bad because this is exactly what makes the large function, well, large?
3 Answers 3
It is a matter of opinion, but I would avoid nesting functions unless it was actually a necessary and deliberate part of your design.
When you nest functions, in most languages, you end up with some sort of mechanical effect. The most common, and interesting, is to close over the lexical scope of a variable that can be used inside the body, but others (eg: visibility of the function) also show up some of the time.
Those are typically awesome tools, when used right - but they are complex tools, because they can result in non-local or non-obvious effects when you first glance at the code.
If you don't use them, many people will read the code and not see anything doing that - so will assume they missed it, and look again, trying to work out why you did it that way, and not in a separate scope.
You also risk that future programmers will deliberately or even accidentally close over something they didn't intend to, by not noticing the risk right there.
Finally, if your function declaration declares a named function outside the scope of the enclosing function, just avoid it. That is super confusing to everyone.
As to the final note: because individual functions help delimit code, nesting functions is less troublesome than a single giant function, but ultimately it does mean reading a lot more code to understand doTooMuch()
- especially if you can hide code between the nested function declarations, or need to check that nobody did.
-
-1: Javascript is not "most languages". Nesting functions in Javascript is normal practice.kevin cline– kevin cline02/29/2012 19:20:28Commented Feb 29, 2012 at 19:20
-
2@kevincline nesting functions in JavaScript is a common bad practiceRaynos– Raynos03/01/2012 11:19:27Commented Mar 1, 2012 at 11:19
-
@Raynos: If you don't nest them, where are you going to put them? Thee are no classes to contain them. Here is some typical code:
jquery(function($){ $('#id').click(function(){...}); }
kevin cline– kevin cline03/01/2012 15:50:36Commented Mar 1, 2012 at 15:50 -
@kevincline ... Typical code for noobs, you need functions nested one deep. And that's because javascript has no module scope, so you need that anonymous closure.Raynos– Raynos03/01/2012 16:29:29Commented Mar 1, 2012 at 16:29
-
And if that click executes an Ajax call, with a completion callback? Now you have functions nested two levels. Sure, you could limit the nesting by assigning the anonymous closures to variables. Is that really better?kevin cline– kevin cline03/01/2012 16:59:08Commented Mar 1, 2012 at 16:59
This is one of those questions that have no right answer and words like "personal preference", "team practice" come to mind. In my opinion, little functions (now here's another subjective thing) that aren't used anywhere belong inside their parent functions, especially when they can be unnamed.
This question has no right answer, because neither choice maximizes encapsulation. If you nest them, they still have access to variables they shouldn't. If you don't, then other functions have access to functions they shouldn't. Either way, you lose.