Boolean Expression Simplification
When a function returns true or false based on a condition, there's no need for an if-else block:
//verbose
if (score >= 60) {
return true;
} else {
return false;
}
//concise
return score >= 60;
Caching Array Length in Loops
Store the array length in a variable before the loop to avoid recalculating it on each iteration:
//recalculates length every iteration
for (let i = 0; i < items.length; i++) {
process(items[i]);
}
//length cached once
for (let i = 0, total = items.length; i < total; i++) {
process(items[i]);
}
This prevents repeated property access, which improves performance especially with larger arrays.
Implicit Boolean Conversion for Strings
JavaScript treats non-empty strings as truthy. This allows for cleaner conditionals:
//explicit check
if (inputValue !== "") {
handleInput();
}
//implicit check
if (inputValue) {
handleInput();
}
Note that whitespace strings are truthy, so this approach works for meaningful content checks.
Implicit Boolean Conversion for Numbers
Non-zero numbers evaluate to true in boolean contexts:
//explicit check
if (count !== 0) {
updateDisplay();
}
//implicit check
if (count) {
updateDisplay();
}
Flattening Nested Conditionals
Deeply nested conditionals reduce readability. Conisder combining conditions or using early returns:
//nested approach
if (product.id === 100) {
if (product.name !== "") {
if (product.category === "electronics") {
applyDiscount();
}
}
}
//combined conditions
if (product.id === 100 && product.name && product.category === "electronics") {
applyDiscount();
}
//early return pattern
if (product.id !== 100) return;
if (!product.name) return;
if (product.category !== "electronics") return;
applyDiscount();
Consolidating Variable Declarations
Group related variables under a single declaration:
//multiple declarations
var userName = "Alice";
var userAge = 25;
var userRole = "admin";
var temp;
//consolidated
var userName = "Alice",
userAge = 25,
userRole = "admin",
temp;
Minimizing DOM Access
DOM operations are expensive. Perform all data manipulation first, then update the DOM once:
//DOM access inside loop
for (let i = 0; i < 100; i++) {
result += data;
document.querySelector(".output").textContent = result;
}
//single DOM update after loop
for (let i = 0; i < 100; i++) {
result += data;
}
document.querySelector(".output").textContent = result;
Avoiding Chained Assignments
Chained assignments can accidentally create unintended global variables:
//problematic - x becomes global
function initialize() {
var a = x = 10;
}
//correct approach
function initialize() {
var a = 10,
x = 10;
}
The first example leaks x to the global scope because the rightmost assignment is evaluated first without var.
Short-Circuit Evaluation with &&
The && operator executes the right side only when the left side is truthy:
//traditional if
if (userAge > 18) {
showContent();
}
//short-circuit
userAge > 18 && showContent();
This pattern is useful for conditional function calls but may reduce readability for complex expressions.
Short-Circuit with Assignment
Building on short-circuit evaluation, you can perform assignments within conditions:
//separate operations
if (isValid) {
config.name = "default";
}
//combined approach
if (isValid && (config.name = "default")) {
proceed();
}
Use this pattern sparingly and add comments to clarify intent, as readers might mistake = for ==.
Warning: When assigning falsy values like empty strings, 0, or null, the condition evaluates to false and the block won't execute.
Default Values with || Operator
The || operator executes the right side when the left side is falsy:
//explicit check
if (configValue === "") {
configValue = "default";
}
//using ||
configValue = configValue || "default";
This pattern works well for establishing defaults but fails when 0 or false are valid intended values.
Using Increment and Decrement Operators
//verbose
counter = counter + 1;
counter = counter - 1;
//concise
counter++;
counter--;
Correct Type Checking
The typeof operator returns lowercase strings, not capitalized ones:
//incorrect - always false
if (typeof name === "String") {}
//correct
if (typeof name === "string") {}
For reference types, use instanceof instead:
var list = [];
if (list instanceof Array) {
//works for reference types
}
Prefer Regular Expressions Over Loops
For string pattern matching, regex is typically more efficient than character-by-character iteration:
//loop-based approach
function convertCase(text) {
var chars = text.split(''),
len = chars.length,
result = [];
for (var i = 0; i < len; i++) {
if (/[A-Z]/.test(chars[i])) {
result.push('-' + chars[i].toLowerCase());
} else {
result.push(chars[i]);
}
}
return result.join('');
}
//regex-based approach
function convertCase(text) {
return text.replace(/([A-Z])/g, '-$1').toLowerCase();
}
Parameter Object Pattern
When a function requires many parameters, group them into an object:
//many parameters
function createUser(username, password, email, phone, address, birthdate) {
//implementation
}
//parameter object
function createUser(userData) {
var username = userData.username,
password = userData.password,
email = userData.email,
phone = userData.phone;
//implementation
}
This improves readability and makes parameter order irrelevant.
Strict Equaltiy Comparison
Always use strict equality to avoid type coercion surprises:
var numericOne = 1;
var stringOne = "1";
//loose comparison - evaluates to true
if (numericOne == stringOne) {
console.log("equal");
}
//strict comparison - evaluates to false
if (numericOne === stringOne) {
console.log("equal");
} else {
console.log("not equal");
}
Ternary Operator for Simple Conditionals
For simple value assignments based on conditions, the ternary operator is concise:
//if-else block
if (temperature > 30) {
status = "hot";
} else {
status = "comfortable";
}
//ternary
status = temperature > 30 ? "hot" : "comfortable";