JavaScript has grown from a simple scripting language to power much of the modern web. With its dynamic capabilities and ubiquity, JavaScript contains many hidden gems to help write better code.
In this article, we’ll explore 20 JavaScript tricks and Best Practices – from clever techniques to design patterns – that can level up your code.
20 JavaScript Tricks and Best Practices:
Conditional (Ternary) Operator
The ternary operator allows implementing conditional logic in a concise way:
let age = 26;
let drink = age >= 21 ? 'Beer' : 'Juice';
console.log(drink); // 'Beer'
This assigns drink based on a conditional test. Much more compact than full if/else statements.
Nullish Coalescing Operator
The ?? operator returns the right-hand value if the left is null/undefined, otherwise returns the left:
let name = null;
let userName = name ?? 'John';
console.log(userName); // 'John'
This handy operator defaults to a value if the original value is nullish.
Optional Chaining
The ?. operator accesses objects/properties safely without explicitly checking for null values:
let customer = {
name: 'Carl',
address: {
street: 'Main St'
}
};
let street = customer?.address?.street;
console.log(street); // 'Main St'
This simplifies nested accessor logic avoiding pesky cannot read property of undefined errors.
Array Destructuring
Destructuring allows neatly assigning elements of arrays to variables:
let arr = [1, 2, 3];
let [x, y] = arr;
console.log(x); // 1
console.log(y); // 2
Destructuring is excellent for extracting elements from arrays in a clean way.
Object Destructuring
Similarly, destructuring extracts fields from objects:
let person = {
name: 'Ruby',
age: 28
}
let { name, age } = person;
console.log(name); // 'Ruby'
Destructuring objects avoids verbose property access code.
Spread Operator
The spread syntax expands iterables into elements:
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5];
console.log(arr2); // [1, 2, 3, 4, 5]
This provides a shorthand for pushing items into arrays or combining arrays.
Rest Parameter
The rest parameter collects remaining elements into an array:
function sum(...numbers) {
return numbers.reduce((total, n) => total + n);
}
sum(1, 2, 3, 4, 5); // 15
Rest parameters are great for gathering trailing parameters into a usable array.
Array Methods
Handy array methods like map, filter, reduce, find, and forEach eliminate verbose loops:
let people = [
{ name: 'John', age: 20 },
{ name: 'Peter', age: 23 },
{ name: 'Mark', age: 16}
];
let under20 = people.filter(person => person.age < 20);
console.log(under20); // [{name: 'Mark', age: 16}]
Leveraging array methods makes processing arrays concise.
Object shorthand
ES6 introduced shortcuts for assigning properties from variables:
let name = 'John';
let age = 20;
let person = {
name,
age
};
console.log(person); // {name: 'John', age: 20}
The property name can use the variable directly avoiding repetition.
Arrow Functions
Arrow functions provide a concise syntax for anonymous functions:
let sum = (a, b) => a + b;
console.log(sum(4, 6)); // 10
No need to type out function
each time. Arrow functions encourage minimalism.
Promise.all
Promise.all runs multiple promises in parallel:
Promise.all([
fetch('/page1'),
fetch('/page2')
]).then(results => {
// Parallel requests complete
});
This allows firing off multiple async requests and handling all results together.
async/await
Async/await offer a clean syntax for working with async code:
async function fetchPages() {
let page1 = await fetch('/page1');
let page2 = await fetch('/page2');
return [page1, page2];
}
Async/await enables writing async code that reads like synchronous code.
Truthy/Falsy
In JavaScript, many values evaluate to true/false implicitly:
let score = 0;
if (score) {
// Not entered
}
let user;
if (!user) {
// User not logged in
}
This leverages how elements like 0, empty strings, null etc. are falsy while objects/arrays are truthy.
Implicit Returns
Arrow functions allow implicit returns:
const add = (a, b) => a + b;
console.log(add(2, 5)); // 7
The function will automatically return the evaluation of the expression.
Object Property Value Shorthand
Object literals can use variable names directly as property values:
let x = 10;
let y = 20;
let coords = { x, y };
console.log(coords); // {x: 10, y: 20}
More concise than specifying the property:value explicitly.
Default Parameters
Default parameters allow initializing arguments to a default if undefined:
function createPost(title, content, published = false) {
// ...
}
Now published
will default to false if not passed.
Template Literals
Template literals provide an elegant way to interpolate variables in strings:
let person = 'John';
let age = 20;
console.log(`Hello ${person}, you are ${age} years old!`);
Much cleaner than string concatenation.
Classes
ES6 classes provide a cleaner syntax for functions & prototypes:
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
let person1 = new Person('John');
person1.sayName(); // 'John'
This enforces object-oriented principles in JavaScript.
Modules
Modules allow encapsulating code into reusable files that can be imported:
// utils.js
export function sum(x, y) {
return x + y;
}
// index.js
import { sum } from './utils.js';
Modules are integral to organizing JavaScript projects.
?? Chaining
The ?? chaining operator stops evaluation if the previous value is null/undefined:
let customer = {
name: 'Carl',
address: {
street: 'Main St'
}
};
let street = customer?.address?.street;
console.log(street); // 'Main St'
This avoids nesting if checks for optional properties.
While just scratching the surface, these examples illustrate some of the powerful constructs that make JavaScript such a versatile language. Mastering these concepts takes practice – but elevates your code!