In this chapter, we will explore patterns for namespacing in JavaScript. Namespaces can be considered a logical grouping of code units under a unique identifier. You can reference the identifier in many namespaces, and each identifier can contain a hierarchy of nested (or sub) namespaces.
In application development, we employ namespaces for many important reasons. JavaScript namespaces help us avoid collisions with other objects or variables in the global namespace. They’re also handy for helping organize blocks of functionality in a codebase so that it can be more easily referenced and used.
Namespacing any serious script or application is critical because it’s crucial to safeguard our code from breaking in the event of another script on the page using the same variable or method names we are. With the number of third-party tags regularly injected into pages, this can be a common problem we all need to tackle at some point in our careers. As a well-behaved “citizen” of the global namespace, it’s also imperative that we try our best not to prevent other developers’ scripts from executing due to the same issues.
While JavaScript doesn’t have built-in support for namespaces like other languages, it does have objects and closures that you can use to achieve a similar effect.
You can find namespaces in almost any serious JavaScript application. Unless we’re working with a simple code snippet, we must do our best to ensure that we’re implementing namespacing correctly, as it’s not just easy to pick up; it’ll also avoid third-party code destroying our own. The patterns we’ll be examining in this section are:
Single global variables
Prefix namespacing
Object literal notation
Nested namespacing
Immediately invoked function
Expressions
Namespace injection
One popular pattern for namespacing in JavaScript is opting for a single global variable as our primary object of reference. Here’s a skeleton implementation of this where we return an object with functions and properties:
const
myUniqueApplication
=
(()
=>
{
function
myMethod
()
{
// code
return
;
}
return
{
myMethod
,
};
})();
// Usage
myUniqueApplication
.
myMethod
();
// In this updated example, we use an immediately invoked function expression
// (IIFE) to create a unique namespace for our application, which is stored in
// the myUniqueApplication variable. The IIFE returns an object with functions
// and properties, and we can access these using dot notation
// (e.g., myUniqueApplication.myMethod()).
Although this works for certain situations, the biggest challenge with the single global variable pattern is ensuring that no one else has used the same global variable name as we have on the page.
One solution to the problem mentioned, as noted by Peter Michaux, is to use prefix namespacing. It’s a simple concept at heart, but the idea is we select a unique prefix namespace we wish to use (in this example, myApplication_
) and then define any methods, variables, or other objects after the prefix as follows:
const
myApplication_propertyA
=
{};
const
myApplication_propertyB
=
{};
function
myApplication_myMethod
(){
//...
}
This effectively decreases the chances of a particular variable existing in the global scope, but remember that a uniquely named object can have the same effect.
This aside, the biggest issue with the pattern is that it can result in many global objects once our application grows. There is also a heavy reliance on our prefix not being used by any other developers in the global namespace, so be careful if opting to use this.
For more on Peter’s views about the single global variable pattern, read his excellent post.
Object literal notation, which we also cover in the Module pattern section, can be thought of as an object containing a collection of key-value pairs with a colon separating each pair of keys and values, where keys can also represent new namespaces:
const
myApplication
=
{
// As we've seen, we can easily define functionality for
// this object literal...
getInfo
()
{
//...
},
// but we can also populate it to support
// further object namespaces containing anything
// anything we wish:
models
:
{},
views
:
{
pages
:
{}
},
collections
:
{}
};
One can also opt for adding properties directly to the namespace:
myApplication
.
foo
=
()
=>
"bar"
myApplication
.
utils
=
{
toString
()
{
//...
},
export
()
{
//...
}
}
Object literals don’t pollute the global namespace but assist in organizing code and parameters logically. They are truly beneficial if you wish to create easily readable structures that you can expand to support deep nesting. Unlike simple global variables, object literals often consider tests for the existence of a variable by the same name, so the chances of a collision occurring are significantly reduced.
The following sample demonstrates several ways to check if an object namespace already exists, defining it if it doesn’t:
// This doesn't check for existence of "myApplication" in
// the global namespace. Bad practice as we can easily
// clobber an existing variable/namespace with the same name
const
myApplication
=
{};
// The following options *do* check for variable/namespace existence.
// If already defined, we use that instance, otherwise we assign a new
// object literal to myApplication.
//
// Option 1: var myApplication = myApplication || {};
// Option 2 if( !MyApplication ){ MyApplication = {} };
// Option 3: window.myApplication || ( window.myApplication = {} );
// Option 4: var myApplication = $.fn.myApplication = function() {};
// Option 5: var myApplication = myApplication === undefined ? {} :
// myApplication;
You’ll often see developers opting for Option 1 or Option 2—they are both straightforward and equivalent in terms of their results.
Option 3 assumes that you’re working in the global namespace, but it can also be written as:
myApplication
||
(
myApplication
=
{});
This variation assumes that myApplication
has already been initialized, so it’s only handy for a parameter/argument scenario, as in the following example:
function
foo
()
{
myApplication
||
(
myApplication
=
{}
);
}
// myApplication hasn't been initialized,
// so foo() throws a ReferenceError
foo
();
// However accepting myApplication as an
// argument
function
foo
(
myApplication
)
{
myApplication
||
(
myApplication
=
{}
);
}
foo
();
// Even if myApplication === undefined, there is no error
// and myApplication gets set to {} correctly
Option 4 can help write jQuery plug-ins where:
// If we were to define a new plug-in...
var
myPlugin
=
$
.
fn
.
myPlugin
=
function
()
{
...
};
// Then later rather than having to type:
$
.
fn
.
myPlugin
.
defaults
=
{};
// We can do:
myPlugin
.
defaults
=
{};
This results in better compression (minification) and can save on scope lookups.
Option 5 is a little similar to Option 4 but is a long form that evaluates whether
myApplication
is undefined
inline, such that it’s defined as an object if not and set to a current value for myApplication
if so.
It is shown just for the sake of being thorough, but in most situations, Options 1–4 will more than suffice for most needs.
There is, of course, a great deal of variance in how and where object literals are used for organizing and structuring code. For smaller applications wishing to expose a nested API for a particular self-enclosed module, you may just find yourself using the Revealing Module pattern, which we covered earlier in the book:
const
namespace
=
(()
=>
{
// defined within the local scope
const
privateMethod1
=
()
=>
{
/* ... */
};
const
privateMethod2
=
()
=>
{
/* ... */
};
privateProperty1
=
"foobar"
;
return
{
// the object literal returned here can have as many
// nested depths as we wish; however, as mentioned,
// this way of doing things works best for smaller,
// limited-scope applications in my personal opinion
publicMethod1
:
privateMethod1
,
// nested namespace with public properties
properties
:
{
publicProperty1
:
privateProperty1
},
// another tested namespace
utils
:
{
publicMethod2
:
privateMethod2
}
...
}
})();
The benefit of using object literals here is that they offer us a very elegant key-value syntax to work with—one where we’re able to easily encapsulate any distinct logic or functionality for our application in a way that clearly separates it from others and provides a solid foundation for extending our code:
const
myConfig
=
{
language
:
"english"
,
defaults
:
{
enableGeolocation
:
true
,
enableSharing
:
false
,
maxPhotos
:
20
},
theme
:
{
skin
:
"a"
,
toolbars
:
{
index
:
"ui-navigation-toolbar"
,
pages
:
"ui-custom-toolbar"
}
}
};
Note that JSON is a subset of object literal notation, and there are only minor syntactical differences between it and the preceding code (e.g., JSON keys must be strings). If, for any reason, one wishes to use JSON for storing configuration data instead (e.g., for simpler storage when sending to the backend), feel free to.
An extension of the Object Literal pattern is nested namespacing. It’s another common pattern that offers a lower risk of collision because even if a namespace already exists, it’s unlikely the same nested children do.
For example, something like this:
YAHOO
.
util
.
Dom
.
getElementsByClassName
(
"test"
);
Older versions of Yahoo!’s YUI library regularly used the Nested Object Namespacing pattern. During my time as an engineer at AOL, we also used this pattern in many of our larger applications. A sample implementation of nested namespacing may look like this:
const
myApp
=
myApp
||
{};
// perform a similar existence check when defining nested
// children
myApp
.
routers
=
myApp
.
routers
||
{};
myApp
.
model
=
myApp
.
model
||
{};
myApp
.
model
.
special
=
myApp
.
model
.
special
||
{};
// nested namespaces can be as complex as required:
// myApp.utilities.charting.html5.plotGraph(/*..*/);
// myApp.modules.financePlanner.getSummary();
// myApp.services.social.facebook.realtimeStream.getLatest();
This code differs from how YUI3 approaches namespacing. YUI3 modules use a sandboxed API host object with far less and far shallower namespacing.
We can also opt to declare new nested namespaces/properties as indexed properties as follows:
myApp
[
"routers"
]
=
myApp
[
"routers"
]
||
{};
myApp
[
"models"
]
=
myApp
[
"models"
]
||
{};
myApp
[
"controllers"
]
=
myApp
[
"controllers"
]
||
{};
Both options are readable and organized and offer a relatively safe way of namespacing our application, similar to what we may be used to in other languages. The only real caveat is that it requires our browser’s JavaScript engine first to locate the myApp
object and then dig down until it gets to the function we actually wish to use.
This can mean more work to perform lookups; however, developers such as Juriy Zaytsev have previously tested and found the performance differences between single object namespacing versus the “nested” approach quite negligible.
Earlier in the book, we briefly covered the concept of an immediately invoked function expression (IIFE); an IIFE, which is effectively an unnamed function, is immediately invoked after it’s been defined. If it sounds familiar, it’s because you may have previously come across it referred to as a self-executing (or self-invoked) anonymous
function. However, I feel Ben Alman’s IIFE naming is more accurate. In JavaScript, because both variables and functions explicitly defined within such a context may be accessed only inside of it, function invocation provides an easy means to achieving privacy.
IIFEs are a popular approach to encapsulating application logic to protect it from the global namespace, but they also have their use in the world of namespacing.
Here are examples of IIFEs:
// an (anonymous) immediately invoked function expression
(()
=>
{
/*...*/
})();
// a named immediately invoked function expression
(
function
foobar
()
{
/*..*/
}());
// this is technically a self-executing function which is quite different
function
foobar
()
{
foobar
();
}
A slightly more expanded version of the first example might look like this:
const
namespace
=
namespace
||
{};
// here a namespace object is passed as a function
// parameter, where we assign public methods and
// properties to it
(
o
=>
{
o
.
foo
=
"foo"
;
o
.
bar
=
()
=>
"bar"
;
})(
namespace
);
console
.
log
(
namespace
);
While readable, this example could be significantly expanded to address common development concerns such as defined levels of privacy (public/private functions and variables) as well as convenient namespace extension. Let’s go through some more code:
// namespace (our namespace name) and undefined are passed here
// to ensure: 1. namespace can be modified locally and isn't
// overwritten outside of our function context;
// 2. the value of undefined is guaranteed as being truly
// undefined. This is to avoid issues with undefined being
// mutable pre-ES5.
;((
namespace
,
undefined
)
=>
{
// private properties
const
foo
=
"foo"
;
const
bar
=
"bar"
;
// public methods and properties
namespace
.
foobar
=
"foobar"
;
namespace
.
sayHello
=
()
=>
{
speak
(
"hello world"
);
};
// private method
function
speak
(
msg
)
{
console
.
log
(
`You said:
${
msg
}
`
);
};
// check to evaluate whether "namespace" exists in the
// global namespace - if not, assign window.namespace an
// object literal
})(
window
.
namespace
=
window
.
namespace
||
{});
// we can then test our properties and methods as follows
// public
// Outputs: foobar
console
.
log
(
namespace
.
foobar
);
// Outputs: hello world
namespace
.
sayHello
();
// assigning new properties
namespace
.
foobar2
=
"foobar"
;
// Outputs: foobar
console
.
log
(
namespace
.
foobar2
);
Extensibility is of course key to any scalable namespacing pattern and IIFEs can be used to achieve this quite easily. In the following example, our “namespace” is once again passed as an argument to our anonymous
function and is then extended (or decorated) with additional functionality:
// let's extend the namespace with new functionality
((
namespace
,
undefined
)
=>
{
// public method
namespace
.
sayGoodbye
=
()
=>
{
console
.
log
(
namespace
.
foo
);
console
.
log
(
namespace
.
bar
);
speak
(
"goodbye"
);
}
})(
window
.
namespace
=
window
.
namespace
||
{});
// Outputs: goodbye
namespace
.
sayGoodbye
();
If you want to learn more about this pattern, I recommend reading Ben’s IIFE post for more information.
Namespace injection is another variation on the IIFE in which we “inject” the methods and properties for a specific namespace from within a function wrapper using this
as a namespace proxy. The benefit this pattern offers is the easy application of functional behavior to multiple objects or namespaces and can come in useful when applying a set of base methods to be built on later (e.g., getters and setters).
The disadvantages of this pattern are that there may be easier or more optimal approaches to achieving this goal (e.g., deep object extension or merging), which I cover earlier in the section.
Next we can see an example of this pattern in action, where we use it to populate the behavior for two namespaces: one initially defined (utils
) and another which we dynamically create as a part of the functionality assignment for utils
(a new namespace called tools
):
const
myApp
=
myApp
||
{};
myApp
.
utils
=
{};
(
function
()
{
let
val
=
5
;
this
.
getValue
=
()
=>
val
;
this
.
setValue
=
newVal
=>
{
val
=
newVal
;
}
// also introduce a new subnamespace
this
.
tools
=
{};
}).
apply
(
myApp
.
utils
);
// inject new behavior into the tools namespace
// which we defined via the utilities module
(
function
()
{
this
.
diagnose
=
()
=>
"diagnosis"
}).
apply
(
myApp
.
utils
.
tools
);
// note, this same approach to extension could be applied
// to a regular IIFE, by just passing in the context as
// an argument and modifying the context rather than just
// "this"
// Usage:
// Outputs our populated namespace
console
.
log
(
myApp
);
// Outputs: 5
console
.
log
(
myApp
.
utils
.
getValue
()
);
// Sets the value of `val` and returns it
myApp
.
utils
.
setValue
(
25
);
console
.
log
(
myApp
.
utils
.
getValue
()
);
// Testing another level down
console
.
log
(
myApp
.
utils
.
tools
.
diagnose
()
);
Previously, Angus Croll has suggested using the call API to provide a natural separation between contexts and arguments. This pattern can feel a lot more like a module creator, but as modules still offer an encapsulation solution, we’ll briefly cover it for the sake of thoroughness:
// define a namespace we can use later
const
ns
=
ns
||
{};
const
ns2
=
ns2
||
{};
// the module/namespace creator
const
creator
=
function
(
val
){
var
val
=
val
||
0
;
this
.
next
=
()
=>
val
++
;
this
.
reset
=
()
=>
{
val
=
0
;
}
};
creator
.
call
(
ns
);
// ns.next, ns.reset now exist
creator
.
call
(
ns2
,
5000
);
// ns2 contains the same methods
// but has an overridden value for val
// of 5000
As mentioned, this type of pattern helps assign a similar base set of functionality to multiple modules or namespaces. I would, however, suggest using it only where explicitly declaring functionality within an object/closure as direct access doesn’t make sense.
We’ll now explore some advanced patterns and utilities that I have found invaluable when working on more extensive applications, some of which have required a rethink of traditional approaches to application namespacing. I’ll note that I am not advocating the following as the way to namespace but rather as ways I have found to work in practice.
As we’ve reviewed, nested namespaces can provide an organized hierarchy of structure for a unit of code. An example of such a namespace could be the following: application.utilities.drawing.canvas.2d
. This can also be expanded using the Object Literal pattern to be:
const
application
=
{
utilities
:
{
drawing
:
{
canvas
:
{
paint
:
{
//...
}
}
}
}
};
One of the obvious challenges with this pattern is that each additional layer we wish to create requires yet another object to be defined as a child of some parent in our top-level namespace. This can become particularly laborious when multiple depths are required as our application increases in complexity.
How can this problem be better solved? In JavaScript Patterns, Stoyan Stefanov presents a clever approach for automatically defining nested namespaces under an existing global variable. He suggests a convenience method that takes a single string argument for a nest, parses this, and automatically populates our base namespace with the objects required.
The method he suggests using is the following, which I’ve updated to be a generic function for easier reuse with multiple namespaces:
// top-level namespace being assigned an object literal
const
myApp
=
{};
// a convenience function for parsing string namespaces and
// automatically generating nested namespaces
function
extend
(
ns
,
ns_string
)
{
const
parts
=
ns_string
.
split
(
"."
);
let
parent
=
ns
;
let
pl
;
pl
=
parts
.
length
;
for
(
let
i
=
0
;
i
<
pl
;
i
++
)
{
// create a property if it doesn't exist
if
(
typeof
parent
[
parts
[
i
]]
===
"undefined"
)
{
parent
[
parts
[
i
]]
=
{};
}
parent
=
parent
[
parts
[
i
]];
}
return
parent
;
}
// Usage:
// extend myApp with a deeply nested namespace
const
mod
=
extend
(
myApp
,
"modules.module2"
);
// the correct object with nested depths is output
console
.
log
(
mod
);
// minor test to check the instance of mod can also
// be used outside of the myApp namespace as a clone
// that includes the extensions
// Outputs: true
console
.
log
(
mod
==
myApp
.
modules
.
module2
);
// further demonstration of easier nested namespace
// assignment using extend
extend
(
myApp
,
"moduleA.moduleB.moduleC.moduleD"
);
extend
(
myApp
,
"longer.version.looks.like.this"
);
console
.
log
(
myApp
);
Figure 11-1 shows the Chrome Developer Tools output. Where one would previously have had to explicitly declare the various nests for their namespace as objects, this can now be easily achieved using a single, cleaner line of code.
We’ll now explore a minor augmentation to the Nested Namespacing pattern, which we’ll refer to as the Dependency Declaration pattern. We all know that local references to objects can decrease overall lookup times, but let’s apply this to namespacing to see how it might look in practice:
// common approach to accessing nested namespaces
myApp
.
utilities
.
math
.
fibonacci
(
25
);
myApp
.
utilities
.
math
.
sin
(
56
);
myApp
.
utilities
.
drawing
.
plot
(
98
,
50
,
60
);
// with local/cached references
const
utils
=
myApp
.
utilities
;
const
maths
=
utils
.
math
;
const
drawing
=
utils
.
drawing
;
// easier to access the namespace
maths
.
fibonacci
(
25
);
maths
.
sin
(
56
);
drawing
.
plot
(
98
,
50
,
60
);
// note that this is particularly performant when
// compared to hundreds or thousands of calls to nested
// namespaces vs. a local reference to the namespace
Working with a local variable here is almost always faster than working with a top-level global (e.g., myApp
). It’s also more convenient and more performant than accessing nested properties/subnamespaces on every subsequent line and can improve readability in more complex applications.
Stoyan recommends declaring localized namespaces required by a function or module at the top of our function scope (using the single-variable pattern) and calls this a Dependency Declaration pattern. One of the benefits this offers is a decrease in locating dependencies and resolving them, should we have an extendable architecture that dynamically loads modules into our namespace when required.
In my opinion, this pattern works best when working at a modular level, localizing a namespace to be used by a group of methods. Localizing namespaces on a per-function level, especially where there is significant overlap between namespace dependencies, is something I recommend avoiding where possible. Instead, define it further up and have them all access the same reference.
An alternative approach to automatic namespacing is deep object extension. Namespaces defined using object literal notation may be easily extended (or merged) with other objects (or namespaces) such that the properties and functions of both namespaces can be accessible under the same namespace postmerge.
This is something that’s been made relatively easy to accomplish with JavaScript frameworks (e.g., see jQuery’s $.extend
); however, if looking to extend objects (namespaces) using conventional JS, the following routine may be of assistance:
// Deep object extension using Object.assign and recursion
function
extendObjects
(
destinationObject
,
sourceObject
)
{
for
(
const
property
in
sourceObject
)
{
if
(
sourceObject
[
property
]
&&
typeof
sourceObject
[
property
]
===
"object"
&&
!
Array
.
isArray
(
sourceObject
[
property
])
)
{
destinationObject
[
property
]
=
destinationObject
[
property
]
||
{};
extendObjects
(
destinationObject
[
property
],
sourceObject
[
property
]);
}
else
{
destinationObject
[
property
]
=
sourceObject
[
property
];
}
}
return
destinationObject
;
}
// Example usage
const
myNamespace
=
myNamespace
||
{};
extendObjects
(
myNamespace
,
{
utils
:
{},
});
console
.
log
(
"test 1"
,
myNamespace
);
extendObjects
(
myNamespace
,
{
hello
:
{
world
:
{
wave
:
{
test
()
{
// ...
},
},
},
},
});
myNamespace
.
hello
.
test1
=
"this is a test"
;
myNamespace
.
hello
.
world
.
test2
=
"this is another test"
;
console
.
log
(
"test 2"
,
myNamespace
);
myNamespace
.
library
=
{
foo
()
{},
};
extendObjects
(
myNamespace
,
{
library
:
{
bar
()
{
// ...
},
},
});
console
.
log
(
"test 3"
,
myNamespace
);
const
shorterNamespaceAccess
=
myNamespace
.
hello
.
world
;
shorterNamespaceAccess
.
test3
=
"hello again"
;
console
.
log
(
"test 4"
,
myNamespace
);
This implementation is not cross-browser compatible with all objects and should be considered a proof of concept only. One may find the Lodash.js extend()
method to be a simpler, more cross-browser-friendly implementation to start with.
For developers who are going to use jQuery in their applications, one can achieve the same object namespace extensibility with $.extend
as follows:
// top-level namespace
const
myApplication
=
myApplication
||
{};
// directly assign a nested namespace
myApplication
.
library
=
{
foo
()
{
// ...
},
};
// deep extend/merge this namespace with another
// to make things interesting, let's say it's a namespace
// with the same name but with a different function
// signature: $.extend( deep, target, object1, object2 )
$
.
extend
(
true
,
myApplication
,
{
library
:
{
bar
()
{
// ...
},
},
});
console
.
log
(
"test"
,
myApplication
);
For thoroughness, please check this for jQuery $.extend
equivalents to the rest of the namespacing experiments in this section.
Reviewing the namespace patterns we’ve explored in this section, the option that I would personally use for most larger applications is Nested Object Namespacing with the Object Literal pattern. Where possible, I would implement this using automated nested namespacing. However, this is just a personal preference.
IIFEs and single global variables may work fine for applications in the small to medium range. However, larger codebases requiring both namespaces and deep subnamespaces require a succinct solution that promotes readability and scale. This pattern achieves all of these objectives well.
I recommend trying out some of the suggested advanced utility methods for namespace extension, as they can save time in the long run.
This chapter discussed how namespacing could help bring structure to your JavaScript and jQuery applications and prevent collisions between variables and function names. Organizing our project files in large JavaScript applications with many code files helps you better manage modules and namespaces and enhances the development experience.
We have now covered different aspects of design and architecture using plain JavaScript. We have mentioned React in passing but haven’t discussed any React patterns in detail. In the next chapter, we aim to do just that.