Exception Handling in Java — try catch finally, Custom Exceptions & Best Practices
JavaScript is one of those languages where knowing the right tricks can save you hours of debugging and make your code dramatically cleaner. Whether you are just getting started or have been writing JavaScript for years, there are always a few patterns and behaviours that are worth understanding deeply — not just knowing what they do, but understanding why they work the way they do.
In this post we will go through five practical JavaScript tips and tricks that every developer should know. These are not obscure one-liners for showing off — they are genuinely useful patterns you will use in real projects.
1. Always Use === Instead of ==
This is probably the single most important habit to build early in
JavaScript. The difference between == and
=== trips up beginners and occasionally catches experienced
developers off guard too.
== is the loose equality operator. Before
comparing two values, it performs type coercion —
meaning it automatically converts one or both values to the same type
before checking if they are equal. This leads to some genuinely
surprising results:
// == performs type coercion before comparing
[10] == 10 // true — array is converted to number 10
'10' == 10 // true — string '10' is converted to number 10
[] == 0 // true — empty array is converted to 0
'' == false // true — empty string is falsy, so is false
null == undefined // true — loose equality treats these as equal
=== is the strict equality operator. It
compares both the value and the type without any
conversion. If the types are different, it immediately returns
false:
// === compares value AND type — no conversion
[10] === 10 // false — array is not a number
'10' === 10 // false — string is not a number
[] === 0 // false — array is not a number
'' === false // false — string is not boolean
null === undefined // false — different types
The rule is simple: always use === by
default. Only use == when you specifically need
type coercion, which is rare. Most style guides and linters like ESLint
enforce this rule automatically.
Beyond correctness, === is also slightly faster because
the JavaScript engine skips the type conversion step entirely.
2. Make Use of Falsy Values
In JavaScript, every value is either truthy or
falsy. A falsy value is one that evaluates to
false when used in a boolean context (like an
if statement). There are exactly six falsy values in
JavaScript — no more, no less:
false— the boolean false0— the number zero (also-0and0n)""— an empty string (single or double quotes)null— intentional absence of a valueundefined— a variable that has been declared but not assignedNaN— Not a Number (result of invalid arithmetic)
Everything else in JavaScript is truthy — including empty arrays
[], empty objects {}, the string
"0", and the string "false".
// Checking if a variable has a meaningful value
if (!variable) {
// Runs when variable is false, 0, "", null, undefined, or NaN
console.log("Variable has no value");
}
// Practical examples
let username = "";
if (!username) {
console.log("Please enter a username"); // runs — empty string is falsy
}
let userAge = 0;
if (!userAge) {
console.log("Age is required"); // runs — 0 is falsy (watch out for this!)
}
let userData = null;
if (!userData) {
console.log("No user data found"); // runs — null is falsy
}
Watch out: 0 being falsy can catch you
off guard. If a user's age or score is legitimately 0, a simple
if (!value) check will incorrectly treat it as missing.
In those cases use value === undefined or
value === null instead of relying on falsy checking.
3. Use Short-Circuit Evaluation for Cleaner Conditionals
JavaScript evaluates logical expressions from left to right and stops as soon as the result is determined. This behaviour — called short-circuit evaluation — can be used to write much cleaner conditional code.
The || (OR) operator — use a default value
// Without short-circuit
function greet(name) {
if (!name) {
name = "Guest";
}
console.log("Hello, " + name);
}
// With short-circuit — much cleaner
function greet(name) {
name = name || "Guest";
console.log("Hello, " + name);
}
greet("Randhir"); // Hello, Randhir
greet(); // Hello, Guest
The && (AND) operator — run code only if condition is true
// Without short-circuit
if (user) {
console.log(user.name);
}
// With short-circuit — same thing in one line
user && console.log(user.name);
The ?? (Nullish Coalescing) operator — only fallback on null/undefined
// || treats 0 and "" as falsy — sometimes not what you want
let count = 0;
let display = count || "No items"; // "No items" — wrong! 0 is a valid value
// ?? only falls back when value is null or undefined
let display2 = count ?? "No items"; // 0 — correct!
The nullish coalescing operator ?? was introduced in ES2020
and is now the preferred way to set default values when you want to
preserve 0, false, and empty strings as
valid values.
4. Destructuring — Extract Values Cleanly
Destructuring is one of the most useful features added in ES6. It lets you extract values from arrays and objects into individual variables in a single clean line instead of writing multiple assignment statements.
Object Destructuring
// Without destructuring — repetitive
const user = { name: "Randhir", age: 25, role: "developer" };
const name = user.name;
const age = user.age;
const role = user.role;
// With destructuring — clean and concise
const { name, age, role } = user;
console.log(name); // Randhir
console.log(age); // 25
// With default values
const { name, age, country = "India" } = user;
console.log(country); // India — uses default since user.country is undefined
// With renaming
const { name: fullName } = user;
console.log(fullName); // Randhir
Array Destructuring
// Without destructuring
const colors = ["red", "green", "blue"];
const first = colors[0];
const second = colors[1];
// With destructuring
const [first, second, third] = colors;
console.log(first); // red
console.log(second); // green
// Skip elements with commas
const [, , third] = colors;
console.log(third); // blue
// Swap two variables without a temp variable
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
Destructuring in Function Parameters
// Instead of this
function displayUser(user) {
console.log(user.name + " is " + user.age + " years old");
}
// Do this — destructure directly in the parameter
function displayUser({ name, age }) {
console.log(name + " is " + age + " years old");
}
displayUser({ name: "Randhir", age: 25 });
// Output: Randhir is 25 years old
5. Use the Spread Operator to Copy and Merge
The spread operator (...) was introduced in ES6 and is
one of the most versatile tools in modern JavaScript. It expands an
array or object into individual elements, which makes copying and
merging data structures much simpler.
Copying an Array
// Without spread — both variables point to the same array (shallow reference)
const original = [1, 2, 3];
const copy = original; // NOT a copy — same reference
copy.push(4);
console.log(original); // [1, 2, 3, 4] — original is modified!
// With spread — creates a real independent copy
const original = [1, 2, 3];
const copy = [...original];
copy.push(4);
console.log(original); // [1, 2, 3] — original is untouched
console.log(copy); // [1, 2, 3, 4]
Merging Arrays
const fruits = ["apple", "banana"];
const vegetables = ["carrot", "potato"];
// Merge two arrays into one
const food = [...fruits, ...vegetables];
console.log(food);
// ["apple", "banana", "carrot", "potato"]
// Add items while merging
const more = [...fruits, "mango", ...vegetables];
console.log(more);
// ["apple", "banana", "mango", "carrot", "potato"]
Copying and Merging Objects
const defaults = { theme: "dark", language: "en", fontSize: 14 };
const userPrefs = { theme: "light", fontSize: 16 };
// Merge — userPrefs values override defaults
const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: "light", language: "en", fontSize: 16 }
// Add a property to an object without mutating the original
const updatedUser = { ...user, role: "admin" };
// user is unchanged, updatedUser has the new role
The spread operator is particularly useful in React and Vue development where immutability matters — you never want to directly modify state objects or arrays, so spread gives you a clean way to create modified copies.
Bonus — Quick Reference Cheat Sheet
// 1. Always use strict equality
'10' === 10 // false — correct behaviour
'10' == 10 // true — misleading!
// 2. Six falsy values
Boolean(false) // false
Boolean(0) // false
Boolean("") // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
Boolean([]) // true — empty array is truthy!
Boolean({}) // true — empty object is truthy!
// 3. Short-circuit defaults
let name = input || "Guest"; // fallback if falsy
let count = value ?? 0; // fallback only if null/undefined
user && user.greet(); // call only if user exists
// 4. Destructuring
const { name, age } = user; // object
const [first, second] = arr; // array
const { name: alias } = user; // rename while destructuring
// 5. Spread operator
const copy = [...arr]; // copy array
const merged = [...a, ...b]; // merge arrays
const newObj = { ...obj, key: v }; // copy and add/override
Final Thought
These five patterns — strict equality, falsy values, short-circuit evaluation, destructuring, and the spread operator — are not just tips for writing shorter code. They reflect a deeper understanding of how JavaScript actually works under the hood. Once you internalise them, you will start spotting opportunities to use them naturally without thinking about it.
If there is one to start with today, make it === over
==. Enable an ESLint rule to enforce it, and within a week
it will be automatic. The rest will follow.
Have a JavaScript tip or trick you think should be on this list? Share it with us via our contact page — we would love to hear what patterns you use every day.