On writing JavaScript well.
It’s one thing to create code, it’s another to create code that’s aesthetically pleasing. And pleasing not just in visual appreciation but also the how the design of the code contributes toward the purpose of creating value for users. With thoughtful consideration, it’s possible to decompose the notion of beauty, or good versus bad code, into a set of characteristics that can be used to evaluate alternative styles of code. Code itself is like art, it’s subjective. With the right context and a mutual appreciation of consistency, you can create beautiful code.
Words can’t describe what I can show, watch the free introduction (below) to understand more about what you’ll take away from this course.
You will learn
✓ Identify and apply characteristics that lead to consistent, aesthetically pleasing code. Code that’s a joy to be responsible for.
✓ Learn trade offs and how to come to a consensus as a team about how to approach consistency.
✓ You’ll learn to improve the code you write yourself, and improve existing code, in a productive manner.
✓ You’ll start to see the impact of rewriting or refactoring code and how it can pay huge dividends without much effort.
✓ Learn about tools that take the pain out of writing code well, so you can focus on what the code accomplishes.
Requirements
• This course assumes you have a basic understanding of Java
• Script to the point that you can read and follow along with code examples.
This course is for
More info about the instructor,
Wes Higbee
I’m passionate about helping organizations delight customers. I’ve had decades of experience developing software and working with teams to improve how software is developed. My experience spans everything from the conception of an idea, through implementation and ongoing support. I’ve been interviewed on The Businessology Show and Art of Value about how important value is in software development. I speak extensively both online and offline about software and business. I routinely write about topics of interest including articles featured in MSDN Magazine, InfoQ, VeraSage and JetBrain’s TeamCity blog. I’ve authored several courses on both Pluralsight and Udemy. I love creating courses to distill and share knowledge with people just like you, that have an unquenchable thirst for learning and improvement. Show moreShow less
How to Write Better Javascript
Most web projects involve writing Javascript, these days it’s more popular than ever.
It’s important to know the fundamentals of how to write good Javascript, even if you don’t become a JS Ninja. There are some simple guidelines you can follow to instantly upgrade your skills, and ensure clean, maintainable code.
Before we dive into that, let’s look at some beginner mistakes.
What Not To Do
I’ve seen some horrible Javascript, I mean the type of thing you can’t un-see.
I once saw a file with dozens of jQuery ready functions, one after another:
jQuery(document).ready(function($) < $('.button').click(function() < alert('do something'); >); >); jQuery(document).ready(function($) < $('.another-button').click(function() < alert('do something else'); >); >); jQuery(document).ready(function($) < $('#another-button2').click(function() < alert('do something else'); >); >); jQuery(document).ready(function($) < $('#another-button3').click(function() < alert('do something else'); >); >); . ad infinitum
This is way too much repeated code, and will quickly become difficult to read and maintain. You should only have the document ready function in one place, to initialize your code. We’ll talk more about that in a bit.
(Also, the .ready() function has been deprecated, so you shouldn’t use it anymore)
Another thing I’ve seen is the dreaded nested if statements:
It’s really hard to tell what the conditions are for executing code inside the nested if statements, and it can quickly become overcomplicated. If your code looks like this, you may need to think through how you can simplify.
Another thing we don’t want is jQuery soup. This is where we have a bunch of jQuery functions with no particular organization.
$(function() < $('.click').click(function()< // do something >); $('.header').css(); $('#coffee').hover( makeMeCoffee ); >);
This may work if you are only writing 3 functions, but projects always grow beyond that. No one wants to sort through a 600 line file of jQuery soup. We’ll look at better structure for your JS file later in this article.
There are a lot of bad practices out there, and we can’t cover them all, but here are some more things to avoid.
// Not using a closure means everything is a global, this is bad! var isGlobal = true; // this will show up as window.isGlobal, polluting the global space // Instead, use an anonymous function like below (function() < // not using the var keyword makes a global myVar = 'bad'; var myVar = 'good'; // not caching variables document.getElementById('my-btn').style.color = 'red'; document.getElementById('my-btn').innerHTML = 'Click me'; // better var myBtn = document.getElementById('my-btn'); myBtn.style.color = 'red'; myBtn.innerHTML = 'Click me'; >)();
Avoid globals and always cache your elements. Looking for an element every time you run a function uses a lot of memory, plus it’s just unnecessary.
Now that we have that out of the way, let’s look at some good examples.
Best Practices
We’ve looked at some of the things we shouldn’t do, so let’s look at best practices.
Here’s a boilerplate of how I like to start my script files:
(function(window, document, $, undefined)< 'use strict'; window.myPrefix = <>; myPrefix.init = function() < // get it started >myPrefix.init(); >)(window, document, jQuery);
First of all, we are using a self executing anonymous function. It sounds really fancy, but it’s just an enclosure to make sure we aren’t polluting the global space. We saw above how defining variables outside of an enclosure makes them available in the window object, which can cause collisions and generally makes things messy.
You can put ‘use strict’ inside your closure to get better error messages when you do something you aren’t supposed to. For example:
"use strict"; x = 3.14; // This will cause an error because we didn't use the var keyword
The next thing we do is create a global variable that will hold all of our variables and functions: window.myPrefix = <>. You should prefix this since it will be in the global space, but anything inside of it does not need a prefix. This is similar to using classes in PHP or ES6.
Everything will be contained inside of window.myPrefix, which means we are only adding one thing to the global namespace.
Next we kick things off with an init function: myPrefix.init(). Everything we do inside of our closure needs myPrefix.whatever to ensure it’s all going into our global variable.
Other developers can access myPrefix.init() from their Javascript if they want to manipulate our code. If we just use an anonymous function, other developers can’t access our code.
Writing our code with an enclosure with a prefixed global variable allows us to keep it organized and accessible by other developers.
Here’s an example of caching some selectors, and adding another function.
(function(window, document, $, undefined)< 'use strict'; window.myPrefix = <>; myPrefix.init = function() < // developers can access this myPrefix.cacheSelectors(); myPrefix.doSomething(); >myPrefix.cacheSelectors = function() < // cache our selectors here, can use them throughout the file myPrefix.body = $('body'); myPrefix.classes = 'class1 class2'; >myPrefix.doSomething = function() < // example of using our cached selectors myPrefix.body.addClass( myPrefix.classes ); >myPrefix.init(); >)(window, document, jQuery);
Now we have a nice structure for our file, avoiding globals and caching selectors, and it’s accessible by other developers.
Since we are using jQuery, this file must be enqueued after the jQuery library. Using WordPress, we do this by adding jquery as a dependency for our script like this:
add_action( 'wp_enqueue_scripts', 'prefix_do_scripts' ); prefix_do_scripts() < wp_enqueue_script( 'prefix-js', plugin_dir_url( __FILE__ ) . 'assets/js/prefix-script.js', array( 'jquery' ),'1.0', true ); >
Random Tips
Here are some common issues that we didn’t cover above.
$('.btn').click( function() < // do something >); $('.element').hover( function() < // do something >); $('#target').focus( function() < // do something >);
Instead, you can chain your events by using .on() (formerly .bind). Also, cache and abstract your functions like below.
// cache all the things var body = $('body'); var myHandler = function( e ) < e.preventDefault(); // do something >body // start chaining events .on( 'click', '.btn', myHandler ) .on( 'hover', '.element', myHandler ) .on( 'focus', '#target', anotherHandler );
By chaining our events with .on() and abstracting our callbacks, we make this much easier to read. We can also add all of our events in one place for easier reference, and make sure everything is cached properly.
CSS in our JS
Anything related to CSS or animation should always be handled by adding and removing classes. For example, we don’t want to use:
And in our style.css file we have:
The same applies for hiding and showing elements, and doing animations. You should never use jQuery slideToggle() or animate(), instead add and remove classes that use CSS animation.
If you follow these guidelines you’ll be well on your way to writing clean, maintainable Javascript. Shout out to Justin Sternberg who taught me a lot of this stuff, also if you want to get more advanced check out this post on Angular 2, Typescript, and Ionic 2.
I’m sure there are lots of best practices I missed, let me know your tips in the comments.
* Updated 9/18 to remove jQuery.ready (deprecated)
8 Comments
Great post Scott. I don’t really have sound knowledge on JavaScript, but I have been reading tutorials just like this. I hope to become perfect in coding JavaScript. Thanks for sharing.