First, a pseudo code example:
;(function(foo){
foo.init = function(baz) { ... }
foo.other = function() { ... }
return foo;
}(window.FOO = window.FOO || {}));
Called like so:
FOO.init();
window.FOO = window.FOO || {}
?I understand what the code does... See below for my reason(s) for asking.
I'm calling the passed in global like so:
;(function(foo){
... foo vs. FOO, anyone else potentially confused? ...
}(window.FOO = window.FOO || {}));
... but I just don't like calling that lowercase "foo
", considering that the global is called capitalized FOO
... It just seems confusing.
If I knew the technical name of this technique, I could say:
;(function(technicalname){
... do something with technicalname, not to be confused with FOO ...
}(window.FOO = window.FOO || {}));
I've seen a recent (awesome) example where they called it "exports
":
;(function(exports){
...
}(window.Lib = window.Lib || {}));
I guess I'm just trying to standardize my coding conventions... I'd like to learn what the pros do and how they think (that's why I'm asking here)!
(function (foo) {
...code...
foo.bar = baz;
...more code...
}(window.FOO = window.FOO || {});
There is no formal name for the pattern you describe, because it's three separate patterns combined. Each pattern goes by multiple names, but for this post I will use the following terminology:
The base of the entire pattern is the closure
. It is simply a function that is used to scope variables and functions such that they don't pollute the global namespace:
//these declare window.foo and window.bar respectively
//as such, they pollute the global namespace
var foo;
function bar() {}
Closure, in this case, an Immediately Invoked Functional Expression (IIFE)
(function () {
//these declare foo and bar within the function
//but they are not accessible outside the function
var foo;
function bar() {}
}());
The advantage of keeping variables within a closure is that you won't have to worry about someone overwriting the variables that you're using. This is especially important for temporary variables such as i
or j
that are used often.
The second important part of this pattern is aliasing. Aliasing allows a variable to be defined and used within a closure without needing to worry about what global namespace it resides in.
Without Aliasing(function () {
...
foo = window.SomeFunction(bar, baz);
...
}());
With Aliasing
(function (sf) { //local name
...
foo = sf(bar, baz);
...
}(window.SomeFunction)); //global namespace
This is especially important as it means that the global namespace can be changed across a large JavaScript file by changing the name in a single location. This is A Good Thing™. Additionally, minifiers can shorten the internal alias to a single letter variable name such as a
, making for significant byte savings on minification.
The namespace extension pattern relies on the coalescing behavior of the or operator (||
). In many languages, &&
and ||
return either true
or false
, but in JavaScript, &&
returns the first falsey
value (false
, 0
, ''
, null
, undefined
), and ||
returns the first truthy
value (anything that's not falsey
). For both operators, if the respective type is not found, the last argument is returned. This makes the ||
operator a convenient way of defining a new namespace only if it doesn't already exist.
if (typeof window.Foo === 'undefined') {
window.foo = {};
}
With namespace extension
window.foo = window.foo || {};
This is useful because it allows a namespace to be extended with additional properties and methods without having to worry about which order the properties and methods were defined in.
In this first example, FileA
would need to be executed before FileB
:
window.foo = {};
window.foo.bar = 'baz';
FileB.js
window.foo.fizz = 'buzz';
In this second example, File1
and File2
could be executed in any order:
window.foo = window.foo || {};
window.foo.bar = 'baz';
File2.js
window.foo = window.foo || {};
window.foo.fizz = 'buzz';
Using each pattern together creates a very powerful modular script:
//use foo internally so that you don't have to worry about
//what the global namespace is called
(function (foo) {
//declare variables internally that you want to keep local to the script
var i,
len,
internal,
qux;
//declare functions/properties on the alias when you want to expose them
foo.bar = function () {...};
//extend the global namespace so that existing extensions are persistent
}(window.FOO = window.FOO || {}));