9 ways to level up your JavaScript code
1. Don’t use commas when declaring variables
var a = 2,
b = a + 2,
c = b - 3;var a = 2;
var b = a + 2;
var c = b - 3;
- variables can be easily moved around from line to line without having to worry about the commas.
2. Namespace all your code
var fruit = "apple";var fruit = ["apple", "pear"]; // namespace collisionwindow.Basket = window.Basket || {};
Basket.fruit = "apple";window.Stock = window.Stock || {};
Stock.fruit = "apple";
- Stops naming collisions
3. Utilize the Module pattern
var Basket = (()=>{
var items = [];
return {
addItem: ()=> {},
removeItem: (index)=> {}
};
})();
- The closure created by the Immediately Invoked Function Expression (IIFE) allows privacy. E.g: The items array is only accessible through the returned methods.
- Link to more indepth article
4. Comment your code
/** Class representing a point. */
class Point {
/**
* Create a point.
* @param {number} x - The x value.
* @param {number} y - The y value.
*/
constructor(x, y) {
// ...
}
}
- Allows developers to get a deeper understanding of what is happening in your code
- Can be used to generate online documentation guides
- Industry standard is JSDOC
5. Learn design patterns
- The Observer pattern helps your modules communicate to each other through events thus providing loose coupling in your app.
- The Mediator pattern takes control over a group of objects by encapsulating how these objects interact. E.g: a basket that handles items.
- The Iterator pattern is the underlying pattern for ES2015 generators. Useful to know whats actually going on :D
- The Facade pattern provides an simple interface which encapsulates the end user from complex functionality. E.g: Email module with simple methods such as start, stop and pause;
Not only are these solutions to commonly solved problems, they are a way of describing application structure to other developers fairly simply. E.g: “The basket module is a mediator for all the store items, it communicates to the payment module via an observer”.
6. Pass objects into functions with a large number of arguments
function colorWidget(element, colorValue, colorRange, colorFormat, opacity, onChange) {
}colorWidget($("<div/>"), "#fff", ...);function colorWidget(options) {
var config = _.extend({
element: $("<div/>"),
colorValue: "#000",
colorRange: [0, 255],
colorFormat: "rgb",
opacity: 0.8,
onChange: function(){}
}, options);
}colorWidget({
element: $("<div/>")
});
- Allows new arguments to be added easily
- The developer doesn’t have to worry about the order of the arguments
- Allows the setting of default values easily
This is most commonly seen in the creation of jQuery plugins.
7. Don’t use type constructors unless specifically necessary
var x1 = new Object();
var x2 = new String();
var x3 = new Number();
var x4 = new Boolean();
var x5 = new Array();
var x6 = new RegExp("()");
var x7 = new Function();var x1 = {};
var x2 = "";
var x3 = 0;
var x4 = false;
var x5 = [];
var x6 = /()/;
var x7 = function(){};
- Creation through type constructors is significantly slower.
- Because the end result of the constructor is an Object rather than a primitive value you get nasty side effects like so:
var a = new String("x");
a === "x" //false
a == "x" //truevar b = "dog";
b.woof = true;
b.woof; // undefinedvar c = new String("dog");
c.woof = true;
c.woof; // true
8. Make sure your context is right
var Button = {
count: 0,
click: function() {
this.count += 1;
},
init: function() {
$("button").click(this.click);
}
};Button.init();
From a glance this should work however when a user clicks the button we will get an error that count doesn’t exist. This is because the click function is executed in the context of the $("button")
element instead of the Button
object. We can fix this by binding the context to the function:
$("button").click(this.click.bind(this));
// or
$("button").click(()=> this.click());
9. Apply
The
apply()
method calls a function with a giventhis
value andarguments
provided as an array (or an array-like object). — MDN
Some useful instances of using apply:
// emulating "super" in an constructor
SomeConstructor.prototype.somemethod.apply(this, arguments);// passing an array of promises to jQuery.when
$.when.apply($, [$.get(), $.get()]);// finding the max number in an array
Math.max.apply(Math.max, [1,2,3,4,5]);
Bonus Points
Contributed by: Russley Shaw
10. Use let and const over var
let
allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used.
Lets look at a few use cases where this is useful over var
statements:
var elements = document.querySelectorAll('p');
for (var i = 0; i < elements.length; i++) {
// have to wrap in IIFE other i would be elements.length
(function(count){
elements[count].addEventListener('click', function(){
elements[count + 1].remove();
});
})(i);
}// using let
let elements = document.querySelectorAll('p');
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', function(){
elements[i + 1].remove();
});
}
The reason why the top example would be elements.length
is because i
is referenced directly so on the next iteration i
is incremented. When we wrap the code in an IIFE we reference i
under the parameter count
thus removing the direct reference.
const
allows the declaration of variables that cannot be re referenced. This is useful for declaring constants
(the keyword originates from it).
const API_KEY = '2rh8ruberigub38rt4tu4t4';
const PI = 3.14;
However objects and arrays can still be accessed and changed. To stop this use Object.freeze()
:
const API_CONFIG = Object.freeze({
'key': '8ry4iuggi4g38430t5485jmub',
'endpoint': '/some/boring/api/path/'
});API_CONFIG.key = null; // attempt to change
API_CONFIG.key; //= '8ry4iuggi4g38430t5485jmub'const EVENS = Object.freeze([ 2, 4, 6, 8]);
EVENS[2] = 9;
EVENS[2]; //= 6
11. Avoid using “or” when referencing variables
The only reason to avoid doing this is when the variable is allowed to be false
. Take a look at the example below:
var msg = ''; //= should hide the button
var btnMsg = msg || 'Click Me';btnMsg; //= 'Click Me'
The reason this happens is due to the conversion of the "”
into a Boolean which returns false
. As the "”
is counted as false
the or
comparison returns the other side Click Me
.
If you want to have shorthand if statements you can use the ternary operator:
var msg = ''; //= should hide the button
var btnMsg = msg.length < 1 ? msg : 'Click Me';btnMsg; //= ''