20 JavaScript Tricks and Best Practices to Level Up Your Code

20 JavaScript Tricks and Best Practices to Level Up Your Code

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 = {

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 runs multiple promises in parallel:

]).then(results => {
  // Parallel requests complete

This allows firing off multiple async requests and handling all results together.


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.


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.


ES6 classes provide a cleaner syntax for functions & prototypes:

class Person {
  constructor(name) {
    this.name = name;

  sayName() {

let person1 = new Person('John');
person1.sayName(); // 'John'

This enforces object-oriented principles in JavaScript.


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!

Leave a Reply

Your email address will not be published. Required fields are marked *