In case you haven’t been reading my other posts, I need to let you know that I’m a big fan of organization and categorization. I like things that are clean and orderly, things that have distinguishable patterns and rhythm. HTML and CSS fulfill these requirements for me: HTML is rendered in the order in which it appears in a file, and well-written CSS will follow the lead of the HTML.
JavaScript, on the other hand, doesn’t have a universal system of organization; you need to organize it yourself and find a system that works for you, which is preferably one that will work for any other people who will be sharing your code.
JavaScript doesn’t work in the same top-to-bottom clean line as HTML and CSS, although once you get used to the patterns you’ll see it’s quite beautiful. It’s asynchronous, so it’s able to load and execute many functions simultaneously. You may have some functions that return information in multiple spots on the page, or some that need to wait for others before proceeding, and this (quite often) means that lines of code can be connected to functions in distant zip codes before they are linked with their neighbours. (This is something that’s not uncommon in programming languages, but since HTML and CSS aren’t actually programming languages, this could be the first time a front-end developer encounters this type of code flow.)
For the beginner, this can be tough to follow. It’s easy to accidentally reassign the same variables, or to completely lose track of the ones that you have. Namespacing is one way to help keep JavaScript not only organized, but clean and kind to others who may have to work with your code in the future.
What is namespacing?
Namespacing is a system of organizing code that involves grouping similar things together and housing them under the same parent name. The objective is to avoid naming collisions, which is what happens when your code breaks because you accidentally gave two things the same name.
There are a few different approaches to namespacing , but whichever one you use, your approach will operate under the same general premise: attach your variables and functions to the main object so that they are protected from conflicts with other code.
The module pattern using object literal notation is my fave, and will probably look familiar: you’re basically creating a giant object that is filled with a series of key:value pairs that are comma separated. Object literals are ways of organizing code based on behaviour, regardless where they are used on a page, so it makes a lot of sense to have this as part of your foundational code structure.
I like that this scopes variables and functions to the application itself. The object is invoked each time we assign a new variable or function (which are respectively called properties and methods when they are found inside an object), and the variable or function gets attached to the namespace to prevent it from running loose through our code.
Here’s an example: you have a donut shop. You like to keep your donuts organized (who doesn’t?), so you create an empty object that will serve as your namespace.
const donutApp = {};
Then, you add your types function as a method on the donutApp object.
donutApp.types = () => { glazed: {}, filled: {}, sprinkles: {}, plain: {} }
Now, what if you also decided to open a pie shop? Because you’re super organized, you would create a new empty object for your pie shop namespace.
const pieApp = {};
Because you were prepared and tried to future-proof your donut shop code by scoping types to the donutApp object, you’ve ensured that all the code associated with your donut shop will stay attached to the donut shop.
So, what happens if you want to have a types function on the pieAppobject?
pieApp.types= () => { fruit: {}, cream: {}, meringue: {}, custard: {} }
Well, first of all, always do your best to avoid using generic names. typeswould be much clearer if we changed it to donutTypes and pieTypes. But since we’ve been specific about donutApp.types and pieApp.types, we’re able to call one without automatically triggering the other. There’s actually no such thing as a universally-accessible types function in our app right now — but there is a types method on our donutApp and our pieApp.
If you’re incorporating a variety of scripts from a multitude of developers, it is totally likely that you could run into each script repeating common names — like init or validate — that are pretty universal for describing exactly what they do. By creating an object literal to hold your script, you ensure that you’re able to call each method only when you need it, because you’ve built your script to be self-contained and respectful of any other code that it encounters.