Your guess as to the intent of || {} is pretty close.
This particular pattern when seen at the top of files is used to create a namespace, i.e. a named object under which functions and variables can be created without unduly polluting the global object.
The reason why it's used is so that if you have two (or more) files:
var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func1 = {
}
and
var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func2 = {
}
both of which share the same namespace it then doesn't matter in which order the two files are loaded, you still get func1 and func2 correctly defined within the MY_NAMESPACE object correctly.
The first file loaded will create the initial MY_NAMESPACE object, and any subsequently loaded file will augment the object.
Usefully, this also allows asynchronous loading of scripts that share the same namespace which can improve page loading times. If the <script> tags have the defer attribute set you can't know in which order they'll be interpreted, so as described above this fixes that problem too.
Another common use for || is to set a default value for an undefined function parameter also:
function display(a) {
a = a || 'default'; // here we set the default value of a to be 'default'
console.log(a);
}
// we call display without providing a parameter
display(); // this will log 'default'
display('test'); // this will log 'test' to the console
Notice that in some version of IE this code won't work as expected. Because the var, the variable is redefined and assigned so – if I recall correctly the issue – you'll end up to have always a new object. That should fix the issue:
There are two main parts that var FOO = FOO || {}; covers.
#1 Preventing overrides
Imagine you have your code split over multiple files and your co-workers are also working on an Object called FOO. Then it could lead to the case that someone already defined FOO and assigned functionality to it (like a skateboard function). Then you would override it, if you were not checking if it already exists.
Problematic case:
// Definition of co-worker "Bart" in "bart.js"
var FOO = {};
FOO.skateboard = function() {
alert('I like skateboarding!');
};
// Definition of co-worker "Homer" in "homer.js"
var FOO = {};
FOO.donut = function() {
alert('I like donuts!');
};
In this case the skateboard function will be gone if you load the JavaScript file homer.js after bart.js in your HTML because Homer defines a new FOO object (and thus overrides the existing one from Bart) so it only knows about the donut function.
So you need to use var FOO = FOO || {}; which means "FOO will be assigned to FOO (if it exists already) or a new blank object (if FOO does not exist already).
Solution:
var FOO = FOO || {};
// Definition of co-worker Bart in bart.js
FOO.skateboard = function() {
alert('I like skateboarding!');
};
// Definition of co-worker Homer in homer.js
var FOO = FOO || {};
FOO.donut = function() {
alert('I like donuts!');
};
Because Bart and Homer are now checking for the existence of FOO before they define their methods, you can load bart.js and homer.js in any order without overriding each other's methods (if they have different names). So you will always get a FOO object which has the methods skateboard and donut (Yay!).
#2 Defining a new object
If you've read through the first example then you already now what's the purpose of the || {}.
Because if there is no existing FOO object then the OR-case will become active and creates a new object, so you can assign functions to it. Like:
var FOO = {};
FOO.skateboard = function() {
alert('I like skateboarding!');
};
For || operations, JS will return the FIRST "truthy" value it finds (reading left-to-right):
var bob = false || undefined || 0 || null || "hi"
// ^ ^ ^ ^ ^
// nope nope nope nope yip
//
// => bob = "hi"
// --------------
// breaking
// --------------
var bob = false || "hi" || 0 || null || undefined
// ^ ^
// nope yip <-- stops here
// the rest are ignored
//
// => bob = "hi"
Another trick is to use the && (and) to ensure something exists before accessing it.
For && operations, JS will return the LAST "truthy" value it finds (reading left-to-right).
For example if you're trying to read a property from a multi-level object.
var obj = {
foo : {
bar : "hi"
}
}
var bob = obj && obj.foo && obj.foo.bar;
// ^ ^ ^
// yip yip use this
//
// => bob = "hi"
// --------------
// breaking:
// --------------
var bob = obj && obj.foo && obj.foo.sally && obj.foo.bar;
// ^ ^ ^
// yip yip nope <-- stops here,
// ^ and returns the last "yip"
// | the rest are ignored |
// '-----------------------------------------------'
//
// => bob = obj.foo
Both || and && operations are read left-to-right... so you can have things that might normally throw errors toward the right side, since JS will simply stop reading left-to-right once it detects a truthy/falsey value.