I'm studying THREE.js and noticed a pattern where functions are defined like so:
var foo = ( function () {
var bar = new Bar();
return function ( ) {
//actual logic using bar from above.
//return result;
};
}());
(Example see raycast method here).
The normal variation of such a method would look like this:
var foo = function () {
var bar = new Bar();
//actual logic.
//return result;
};
Comparing the first version to the normal variation, the first seems to differ in that:
- It assigns the result of a self-executing function.
- It defines a local variable within this function.
- It returns the actual function containing logic that makes use of the local variable.
So the main difference is that in the first variation the bar is only assigned once, at initialization, while the second variation creates this temporary variable every time it is called.
My best guess on why this is used is that it limits the number of instances for bar (there will only be one) and thus saves memory management overhead.
My questions:
- Is this assumption correct?
- Is there a name for this pattern?
- Why is this used?
I'd like to contribute to this interesting thread by extending to the concept of the revealing module pattern, which ensures that all methods and variables are kept private until they are explicitly exposed.
In the latter case, the addition method would be called as Calculator.add();
The key difference between your code and the Three.js code is that in the Three.js code the variable
tmpObject
is only initialised once, and then shared by every invocation of the returned function.This would be useful for keeping some state between calls, similar to how
static
variables are used in C-like languages.tmpObject
is a private variable only visible to the inner function.It changes the memory usage, but its not designed to save memory.
Your assumptions are almost correct. Let's review those first.
This is called an Immediately-invoked function expression or IIFE
This is the way of having private object fields in JavaScript as it does not provide the
private
keyword or functionality otherwise.Again, the main point is that this local variable is private.
AFAIK you can call this pattern Module Pattern. Quoting:
Comparing those two examples, my best guesses about why the first one is used are:
But if you just need the vanilla object every time, then this pattern will probably not add any value.
It limits the object initialization costs and additionally ensures that all function invocations use the same object. This allows, for example, state to be stored in the object for future invocations to use.
While it's possible that it does limit memory usage, usually the GC will collect unused objects anyways, so this pattern is not likely to help much.
This pattern is a specific form of closure.
I'm not sure if this pattern has a more correct name, but this looks like a module to me, and the reason it is used is to both encapsulate and to maintain state.
The closure (identified by a function within a function) ensures that the inner function has access to the variables within the outer function.
In the example you gave, the inner function is returned (and assigned to
foo
) by executing the outer function which meanstmpObject
continues to live within the closure and multiple calls to the inner functionfoo()
will operate on the same instance oftmpObject
.In the example provided, the first snippet will use the same instance of tmpObject for every call to the function foo(), where as in the second snippet, tmpObject will be a new instance every time.
One reason the first snippet may have been used, is that the variable tmpObject can be shared between calls to foo(), without its value being leaked into the scope that foo() is declared in.
The non immediately executed function version of the first snippet would actually look like this:
Note however that this version has tmpObject in the same scope as foo(), so it could be manipulated later.
A better way to achieve the same functionality would be to use a separate module:
Module 'foo.js':
Module 2:
A comparison between the performance of an IEF and a named foo creator function: http://jsperf.com/ief-vs-named-function