Today, I want to show you how I structure all my JavaScript files at a basic level. Putting some thought into how you organize your code makes it easier for you and other developers to read and work with.
To make this simple, let's look at a really contrived example. For all click events that occur within the #app
element, we want to log the clicked element to the console.
Immediately-invoked function expression
For most projects, I want my code to run immediately when the page loads. I also want to keep it out of the global scope to avoid naming conflicts with other scripts. To do this, I start with an immediately-invoked function expression (IIFE, pronounced 'iffy'):
;(function () {
// Opt into ES5 strict mode
"use strict";
})();
Variables
At the top of my IIFE, I add all my global variables. It's nice to have them all in one place at the top so you can easily find and change them.
For this example, we just need to get the #app
element:
;(function () {
// Opt into ES5 strict mode
"use strict";
//
// Variables
//
// Get the #app element
var app = document.querySelector("#app");
})();
Functions
Next, I add all my functions. Using named, modular functions really helps keep your code more readable and maintainble.
For this example, we'll create a logElement()
function that logs the clicked element to the console:
;(function () {
// Opt into ES5 strict mode
"use strict";
//
// Variables
//
// Get the #app element
var app = document.querySelector("#app");
//
// Functions
//
/**
* Log the clicked element to the console
* @param {Object} event The Event object
*/
function logElement (event) {
console.log(event.target);
}
})();
Inits & Event Listeners
Finally, I add my inits and event listeners to the bottom of the IIFE. This is where I put any code that actually initializes the app, as opposed to just creating variables and functions.
For this example, we just need to add our click handler to the #app
element:
;(function () {
// Opt into ES5 strict mode
"use strict";
//
// Variables
//
// Get the #app element
var app = document.querySelector("#app");
//
// Functions
//
/**
* Log the clicked element to the console
* @param {Object} event The Event object
*/
function logElement (event) {
console.log(event.target);
}
//
// Inits & Event Listeners
//
// Log all click events that occur inside #app
app.addEventListener("click", logElement);
})();
Wrapping up
And there you have it: how I structure all my JavaScript files on a basic level. I recommend keeping the comments and spacing. These will be stripped out from minified production code anyway, so optimize for readability, not brevity.
I'd like to thank Chris Ferdinandi and Todd Motto for influencing my approach. You can find more boilerplates on The Vanilla JS Toolkit, which Chris maintains. Let me know if you'd like me to write about them. 😊