Some of coworkers are saying that nesting functions is bad for performance and I wanted to ask about this.
Lets say I have the function:
function calculateStuff() {
function helper() {
// helper does things
}
// calculateStuff does things
helper();
}
helper is a private function that is only used inside calculateStuff. That's why I wanted to encapsulate this inside calculateStuff.
Is this worse performance wise than doing:
function helper() {
}
function calculateStuff() {
helper();
}
Notice that in the second case, I expose helper to my scope.
In theory, there's a potential performance impact, in that you need to create a new closure context for helper every time calculateStuff is called (because it might reference variables from the enclosing scope).
I'm pretty sure that the JIT compiler in most JavaScript engines should be able to tell that you aren't actually accessing any variables from the parent context, and just skip binding all of those values. I may be missing some edge case where this isn't generally possible, but it seems straighforward-enough.
In any case, we're talking about nanoseconds of overhead per iteration, so unless your code is executed a lot, you'd never notice the time difference. If in doubt, profile it and check...
I decided to follow my own advice, and profile this on jsperf, with Safari 9. I used the do-nothing functions as provided in the original question, to highlight the overhead of just calling a nested function:
Nested functions: 136,000,000 calls per second
Flat functions: 1,035,000,000 cals per second
Oriol's IIFE version: 220,000,000 cals per second
Clearly the flat functions are much faster than either of the alternative versions. However, think about the magnitude of those numbers - even the "slow" version only adds 0.007 microseconds to the execution time. If you do any kind of calculation or DOM manipulation in that function, it'll absolutely dwarf the overhead of the nested function.
With your first code, at each call of calculateStuff, a new copy of helper will be created.
With your second code, all calls will share the same helper, but it will pollute the outer scope.
If you want to reuse helper without polluting the outer scope, you can use an IIFE:
var calculateStuff = (function () {
function helper() {
// helper does things
}
return function() {
// calculateStuff does things
helper();
}
})();
Related
2 questions:
Closures have the advantage of being able to access the outer scopes and therefore are a great tool in our toolbox.
Is it frowned upon just using them to structure the program if scoping is not needed?.
foo = () => {
closure = (_)=> {
...
}
if(...){
closure(bar);
}else{
closure(baz);
}
}
In this case the function does not depend on the scope and could
be moved one level higher without change in functionality. Semantically it makes sense to place it there since it will only be used inside foo.
How do closures behave if they are declared inside loops? Does redeclaration hurt performance?`
foo.forEach( x => {
closure = () => ...
})
Is it frowned upon just using them to structure the program if scoping is not needed?
There is no one way to write JavaScript code (or any other code). This part of the question calls for opinion, which is off-topic for SO. :-)
There are a couple of objective observations that can be made about doing that:
It keeps the functions private, they can only be used in the function they're created in (assuming you don't return them out of it or assign them to variables declared in an outer scope). That could be argued as being good (for encapsulation) and as bad (limited reuse).
Modules probably reduce the desire to do this a bit (though not entirely).
How do closures behave if they are declared inside loops?
A couple of things I need to call out about your example relative to the question you've asked there:
You haven't declared a function at all. You've created one, via a function expression, but you haven't declared one. (This matters to the answer; we'll come back to it in a moment.)
Your example doesn't create a function in a loop, it creates it inside another function — forEach's callback. That function is called several times, but it isn't a loop per se.
This code creates a function in a loop:
for (const value of something) {
closure = () => {
// ...
};
}
It works just like creating a function anywhere else: A new function object is created each time, closing over the environment where it was created (in this case, the environment for each iteration of the loop). This can be handy if it's using something specific to the loop iteration (like value above).
Declaring a function in a loop looks like this:
for (const value of something) {
function foo() {
// ...
}
}
Never do that in loose-mode code, only do it in strict mode (or better yet, avoid doing it entirely). The loose-mode semantics for it aren't pretty because it wasn't specified behavior for a long time (but was an "allowed extension") and different implementations handled it in different ways. When TC39 specified the behavior, they could only specify a subset of situations that happened to be handled the same way across all major implementations.
The strict mode semantics for it are fairly reasonable: A new function object is created every time and the function's identifier exists only in the environment of the loop iteration. Like all function declarations, it's hoisted (to the top of the block, not the scope enclosing the loop):
"use strict";
const something = [1, 2, 3];
console.log(typeof foo); // Doesn't exist here
for (const value of something) {
foo();
function foo() {
console.log(value);
}
}
console.log(typeof foo); // Doesn't exist here
Does redeclaration hurt performance?
Not really. The JavaScript engine only has to parse the code once, creating the bytecode or machine code for the function, and then can reuse that bytecode or machine code when creating each of the function objects and attaching them to the environment they close over. Modern engines are very good at that. If you're creating millions of temporary objects, that might cause memory churn, but only worry about it if and when you have a performance problem that you've traced to a place where you've done it.
I have used JS for two years and my pluralsight accessment rates me as proficient in JS, I understand prototypical inheritance, higher order functions, IIFEs etc and I have used them in real world instances but closures is one of those concept that you understand but can't find any reason why you would want to use them in real world development, I mean I know that if I say,
function expClosure(val){
//do something to val-->anotherVal
return function(val){return anotherVal)};
}
var exp = expClosure(val);
exp(); --> returns the value of anotherVal;
My question is why would I want to do this, or rather what specific instances can lead me to consider using this.
The main benefit to closures is you can "partially apply" a function using a closure, then pass the partially applied function around, instead of needing to pass the non-applied function, and any data you'll need to call it (very useful, in many scenarios).
Say you have a function f that will need in the future 2 pieces of data to operate. One approach is you could pass both pieces in as arguments when you call it. The problem with this approach is if the first piece of data is available immediately, and the second isn't, you'll have to pass it around with f so it's in scope when you want to call the function.
The other option is to give the available data to the function immediately. You can create a closure over the data, have the function reference the external data, then pass the function around by itself.
Option 2 is much simpler.
You can also use closures to implement static variables in functions in languages that don't natively support them. Clojure (the language) implements it's memoize function by having it return a modified version of the passed function that holds a reference to a map representing argument/return value pairs. Before the function is run, it first checks if the arguments already exist in the map. If they do, it returns the cached return value instead of recalculating it.
(Adapted from my answer to another question)
I wrote a bit about this in my practical bachelor thesis(2.2.2)
Hiding variables is a valuable usage of closure. Compared to some other languages variables can't be declared as private, public, etc. in JavaScript, but using closure you can hide variables that can only be used internally. E.g.
function Car() {
var speed = 0;
return {
accelerate: function() {
speed++;
}
}
}
var car = new Car();
car.accelerate();
speed is accessible by accelerate due to closure, but is otherwise completely inaccessible.
Since this question doesn't demand a programmatic answer, I am adding an answer and not a comment.
The example you quoted in the question is, I agree of a closure, and I am sure having access to pluralsight lectures, you well understand closures. So the aforestated example is not the only use case of closures. The closures are the functions which remember the scope in which they were created.
An obvious example of this is a callback registering mechanism which every one uses in jQuery. There are closures everywhere, and many of us have been unknowingly writing closures.
So if you have used redux, you would know the entire concept is based on closure, i.e. encapsulating the data(called state of application). Closure provisions a concept of private variables used in OOPS supporting languages.
I am adding another example of closure below, so you might be able to relate.
function processOrder(amount){
var temp_order_id = +new Date() + 'USERID';
var afterPaymentCompleteOrder = function(status){//callback
//afterPaymentCompleteOrder is a closure as it remembers the scope in which it is created when it is being called. So when ivoked it remembers the value of temp_order_id
if(status){
complete_order_method(temp_order_id);
}
else
delete_order_details(temp_order_id);
}
start_payment_process(amount, afterPaymentCompleteOrder);
}
A powerful feature of Javascript is how you can use closures and higher order functions to hide private data:
function outerFunction(closureArgument) {
var closureVariable = something;
return function innerFunction() {
// do something with the closed variables
}
}
However, this means that every time I call outerFunction, a new innerFunction is declared and returned, which means that outerFunction(arg) !== outerFunction(arg). I wonder to what extent, if any, this might impact performance. As an example, a typical alternative would be to create a constructor that holds the data, and put innerFunction on the prototype:
function Constructor(argument) {
this.argument = argument;
this.variable = something;
}
Constructor.prototype.method = function() {
// do something with this.argument and this.variable
}
In that case, there is a single function that is shared by a number of instances, e.g new Constructor().method === new Constructor().method, but the data can not easily be made private, and the function can only be called as a method, so it has access to its context variables (This is just an example; there are other ways to solve the issue; my question is not actually about constructors and prototypes).
Does this matter from a performance perspective? It seems to me that since a function is always a literal, and the function body itself is immutable, Javascript engines should be able to optimize the above code example so that there shouldn't be a big performance impact because we have "multiple" functions instead of a single, shared function.
In summary: Does running the same function declaration multiple times come with any significant performance penalty, or do Javascript engines optimize it?
Yes, engines do optimise closures. A lot. There is no significant performance or memory penalty.
However, the prototype approach still can be faster, because engines are better at detecting the potential to inline a method call. You will want to step through the details in this article - though it could easily be outdated by newer compiler optimisations.
But don't fear closures because of that, any differences will be negligible for most cases you encounter. If in doubt, and with real need for speed, benchmark your code (and avoid premature optimisation till then). If closures make your code easier to read, write, maintain, go for them. They are a powerful tool that you don't want to miss.
If have a callback that is activated repeatedly such as the following...
Template.foo.rendered = function() {
$(this.firstNode).droppable({
// other arguments
drop: function() {
// some really long function that doesn't access anything in the closure
}
});
}
Should I optimize it to the following?
dropFunction = function() {
// some really long function that doesn't access anything in the closure
}
Template.foo.rendered = function() {
$(this.firstNode).droppable({
// other arguments
drop: dropFunction
});
}
In this case, the rendered callback is a Meteor construct which runs asynchronously over a DOM node with template foo whenever they are constructed; there can be quite a few of them. Does it help to declare the function somewhere in a global closure, to save the Javascript engine the hassle of keeping track of an extra local closure, or does it not matter?
I don't believe that in modern browsers that there will even be a difference. When creating a closure object, V8 determines what variables your function uses, and if you don't use a variable it won't put it in the closure object(I read this somewhere online a while back, sorry I can't find the link*SEE BELOW*). I assume any browser that compiles JavaScript would do the same.
What will be optimized is the creation of the function. In the second example the drop function is created at the same time as the rendered function, in the first it's re-created every time the rendered is called. If this was in a long for loop that might be worth optimizing.
I personally think the first example is a lot easier to read and maintain. And as I said in a comment on the question you(or the person editing this code in the future) could accidentally overwrite the function variable(in an event handler or something) and you could have a hard to find bug on your hands. I would suggest saying with number 1, or wrapping everything in a self-executing function so dropFunction has a smaller scope and less chance of being overwritten, like so:
(function () {
var dropFunction = function() {
// some really long function that doesn't access anything in the closure
}
Template.foo.rendered = function() {
$(this.firstNode).droppable({
// other arguments
drop: dropFunction
});
}
})();
EDIT: I found the link, it was actually in a blog post about a closure memory leak in Meteor!
http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html
Here's the portion I mentioned:
JavaScript implementations (or at least current Chrome) are smart enough to notice that str isn’t used in logIt, so it’s not put into logIt’s lexical environment, and it’s OK to GC the big string once run finishes.
I'll start this by saying I don't know anything about meteor :/ but if I'm understanding what happens correctly, basically:
Template.foo.rendered
Gets called repeatedly. When that occurs, you construct and object + define a new function on it "drop" which is eventually invoked. If that is the case, you are better off from a performance perspective defining drop once at parse time. But the benefit probably depends on how often rendered is called.
As for why - I posted something similar here:
Performance of function declaration vs function expressions in javascript in a loop
And I think #soktinpk's answer I think is a great summary.
If you look at the jsperf in the above link it may not initially seem directly applicable, but if my assumed statements above are true it is in fact is - because the question at hand boils down to how expensive is to define a function at runtime vs parse time and are you defining this function at runtime over and over again.
If you look at the performance of the loops where a function is defined at runtime vs the loops where functions are defined at parse time (or defined at parse time and hoisted), the parse time loop run significantly faster.
I believe that the equivalent of what meteor is doing in your example is probably something like this jsperf: http://jsperf.com/how-expensive-is-defining-a-function-at-runtime2
What I have done here is created two loops that simulate your scenario being invoked over and over again. The first invokes a function that creates and object and function and passes it to another function for invocation.
The second creates and object that references a function and passes it to another function for invocation. The difference in performance looks significant (58% in chrome).
I often come across Javascript code snippets that consist of many anonymous functions that are called where they are created, such as here:
var prealloc = (function() {
// some definitions here
return function prealloc_win(file, size, perms, sparseOk) {
// function body
};
})();
// can be called like this:
prealloc(...);
So this calls an anonymous function which returns another function prealloc_win. To me this seems equivalent to instantiating a class where the resulting object exposes the function prealloc_win:
function preallocObj() {
// some definitions here
this.prealloc_win = function(file, size, perms, sparseOk) {
// function body
};
}
prealloc = new preallocObj();
// can be called like this:
prealloc.prealloc_win(...);
Is this assumption correct? What are the benefits of using anonymous functions that are called directly? And why is this idiom so often seen in Javascript, but not often in other languages which could be written in the same way (C, C++, Python)?
The deal is that the preallocObj class says that this is something that could be
instantiated multiple times. I could just create more instances of it even though it wasn't really designed for that. You could do some hacks to prevent that but it's easier just to use the immediately invoked anonymous function for this.
With the immediately created and invoked anonymous function, a "class" is created, instantly "instantiated" and assigned to prealloc and
there is no way to reference the original anonymous function that created the prealloc object after this. It was created, invoked and lost.
You pretty much have the right idea. The benefits of this module pattern/function builder are that the resultant function can enclose its own internal definitions or state.
It's basically just a way to create a function with private variables or constants. Consider the less efficient alternative:
var prealloc = function() {
// some definitions here
// function body
}
Every time this function is called it would reassign/instantiate its variables, adding unnecessary performance overhead and overwriting any state data that resulted from previous calls.
This method is useful when there are some variables that are important to the workings of a function that you want only private access to or that you need to persist between invocations without contaminating the outer scope.
Javascript is fundamentally very different to C++, JAVA and Python and should be written in differnt ways. At the risk of repetition, Javascript is not an OOP language it is a prototype language. Douglas Crockford (inventor of JSON) at Yahoo has some wonderful articles and particuarily Videos entitled 'Javascript - the good parts' you should watch them all.