Nested helper functions can be useful for making your code more understandable. Google even recommends using nested functions in their style guide. I'm wondering about the instantiation of these nested functions and performance. For example,
work(1);
work(2);
function work(a) {
// do some stuff
log();
// do some more stuff
function log() {
console.log(a);
}
}
work
is instantiated once, but is log
instantiated twice?
If log
is instantiated every time work
is executed, would it generally be recommended not to nest functions? Instead, write code like the following
work(1);
work(2);
function work(a) {
// do some stuff
log(a);
// do some more stuff
}
function log(a) {
console.log(a);
}
These examples are overly trivial and the question is more about the general case.
You should not nest it, because otherwise the nested function will be re-created every time you call the outer function. Show activity on this post. Since function B isn't used anywhere else you might as well just make it an inside funtion within function A because that's the only reason why it exists.
One disadvantage of declaring a nested function is the fact that it will be created inside function's environment every time you call the parent function. In theory, this could decrease performance if the parent function is called frequently. But, nested functions are very much used in Javascript.
So, in Python, nested functions have direct access to the variables and names that you define in the enclosing function. It provides a mechanism for encapsulating functions, creating helper solutions, and implementing closures and decorators.
Users typically create nested functions as part of a conditional formula. For example, IF(AVERAGE(B2:B10)>100,SUM(C2:G10),0). The AVERAGE and SUM functions are nested within the IF function.
work is instantiated once, but is log instantiated twice?
Yes, on each call to work.
would it generally be recommended not to nest functions?
Why not? I presume you're hinting at performance issues.
Whether a practice is good or bad depends on your reasons for using it. In the case of simple helpers, it's good to keep them local because it means you can make them suitable just for your special case and not worry about the extra cruft of a general function. E.g. to pad a number with a leading zero:
function pad(n) {
return (n<10? '0' : '') + n;
}
works very well as a helper where n is expected to always be in the range 0 to 99, but as a general function is missing a lot of features (dealing with non–number n, -ve numbers, etc.).
If you are concerned about performance, you can always use a closure so the helper is only instantiated once:
var work = (function() {
function log() {
console.log(a);
}
return function (a) {
// do some stuff
log();
// do some more stuff
};
}());
Which can also make sense where log is used by more than one function within the closure.
Note that for a single case, this is very much a micro optimisation and not likely to deliver any noticeable difference in performance.
Nested function-objects are instantiated and added to the LexicalEnvironment
created when an enclosing function is run. Each of these nested functions will also have a [[Scope]]
property created on them. In addition when a nested function is run, a new LexicalEnvironment
object will be created and the [[Scope]]
copied to its outer
property.
When the enclosing function completes, then the nested function-object and its associated memory will be eligible for garbage collection.
This process will repeat for every call to the outer function.
Contrast this with your second implementation, where the function-object need only be created once; likewise its garbage collection.
If this is a "hot" function (i.e. called many times) then the second implementation is infinitely preferable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With