React is fundamentally plain JavaScript. If you ever struggle with state updates, unintended re-renders, or props drilling, the issue is rarely React itself—it is usually a missing piece of modern ECMAScript fundamentals.
- Modern Variables: const, let, Scoping, and Retiring var In legacy JavaScript, var was function-scoped and subject to unpredictable hoisting behaviors:
JavaScript
// The legacy problem: var leaks out of block statements
if (true) {
var framework = "React";
}
console.log(framework); // "React" (escaped block scope)
Modern JS introduces block scoping with let and const:
const: Enforces constant references. Variables cannot be reassigned. Use this by default (roughly 95% of the time in React components).
let: Enables reassignable block-scoped variables (ideal for counters, loops, or flags).
Temporal Dead Zone (TDZ): Unlike var, accessing let or const before declaration throws a ReferenceError rather than returning undefined.
JavaScript
/
/ Modern standard:
const API_URL = "https://api.store.com/v1";
let retryCount = 0;
if (retryCount === 0) {
const localMessage = "Initial attempt";
retryCount += 1;
}
// localMessage is completely inaccessible here (ReferenceError)
- Arrow Functions and Lexical this Arrow functions (() => {}) give developers a concise syntax and, more crucially, lexical this scoping. They do not bind their own this, arguments, or super.
Concise Syntax & Implicit Returns
In React, implicit returns are frequently used for rendering JSX:
// Explicit return
const UserCard = (props) => {
return <div>{props.name}</div>;
};
// Implicit return (no 'return' keyword, wrapped in parentheses)
const UserCard = ({ name }) => (
<div className="card">
<h3>{name}</h3>
</div>
);
Lexical this vs Standard Functions
In traditional functions, this is determined by how the function is invoked. With arrow functions, this is bound to the surrounding lexical context:
JavaScript
const counterService = {
count: 0,
start() {
// Normal function inside setInterval would rebind 'this' to window/timeout
setInterval(() => {
this.count++;
console.log(`Live Count: ${this.count}`);
}, 1000);
}
};
- Essential Array Methods: map, filter, reduce, find, some/every
JavaScript
const products = [
{ id: "p1", title: "Wireless Mouse", price: 30, inStock: true },
{ id: "p2", title: "Mechanical Keyboard", price: 120, inStock: false },
{ id: "p3", title: "USB-C Hub", price: 45, inStock: true }
];
// 1. filter: Available items only
const available = products.filter(p => p.inStock);
// 2. map: Transform to rendered strings / components
const catalogView = available.map(p => `${p.title} - $${p.price}`);
// 3. reduce: Calculate aggregate total
const inventoryValue = products.reduce((sum, p) => sum + p.price, 0);
// 4. find: Grab exact target
const keyboard = products.find(p => p.id === "p2");
// 5. some: Availability check
const hasOutOfStock = products.some(p => !p.inStock); // true
- Destructuring (Arrays & Objects) and Default Parameters
Destructuring provides syntactic shortcuts to extract nested values directly into clean variables.
Object Destructuring in Props
JavaScript
// Instead of accessing props.theme, props.title, props.isActive
function Button({ theme = "primary", title = "Submit", onClick }) {
return (
<button className={`btn btn-${theme}`} onClick={onClick}>
{title}
</button>
);
}
Array DestructuringArray destructuring maps variables based on positional indexing (the exact mechanism powering React's useState hook):
JavaScript
const [selectedTab, setSelectedTab] = ["overview", () => {}];
- Rest and Spread Operators (...) While both use three dots (...), their intents are distinct: Spread Operator (...): Expands elements of an array or properties of an object into a new structure. Rest Parameter (...args): Condenses multiple distinct arguments into a single collected array. Immutable State Updates with Spread Never mutate React state directly; always create new copies:
JavaScript
const userProfile = { id: 101, name: "Ali", settings: { dark: true } };
// Updating user profile immutably
const updatedProfile = {
...userProfile,
name: "Alireza", // overrides 'name'
role: "Admin" // appends new field
};
// Adding an item to an array immutably
const cart = ["Mouse", "Keyboard"];
const nextCart = [...cart, "Monitor"];
Rest Parameter in Components
JavaScript
// Collect rest of props to pass through to native elements
const CustomInput = ({ label, ...nativeInputProps }) => (
<label>
{label}
<input {...nativeInputProps} />
</label>
);
- Immutability: Shallow vs Deep Comparison React optimizes renders using shallow equality comparison (Object.is() / ===).
Shallow Copy / Comparison: Compares only top-level references. If an object reference hasn't changed, React assumes its internals haven't changed either.
The Mutation Trap:
JavaScript
// WRONG: Direct mutation does NOT change object reference!
const state = { count: 0, meta: { tags: ["tech"] } };
state.count = 1;
// If passed to a memoized component or setState:
// previousState === nextState evaluated to TRUE -> NO RE-RENDER!
// RIGHT: Shallow copy creates a new top-level reference
const nextState = { ...state, count: 1 };
console.log(state === nextState); // false -> triggers re-render
// Nested reference gotcha:
// state.meta and nextState.meta still point to the EXACT SAME memory address!
// For nested mutations, you must shallow copy the inner object as well:
const fullyUpdated = {
...state,
meta: {
...state.meta,
tags: [...state.meta.tags, "react"]
}
};
- Async JavaScript: Promises and async/await with try/catch React lifecycles and event handlers communicate with network APIs via asynchronous promises.
JavaScript
// Standard data fetching pattern with async/await and try/catch
async function fetchProducts(category) {
try {
const response = await fetch(`https://api.store.com/products?category=${category}`);
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
const data = await response.json();
return { success: true, payload: data };
} catch (error) {
console.error("Fetch pipeline failed:", error.message);
return { success: false, error: error.message };
} finally {
console.log("Network request completed.");
}
}
- Modular Architecture: Named vs Default Exports JavaScript modules (ESM) enable decoupled, maintainable codebases:
JavaScript
// mathUtils.js
export const TAX_RATE = 0.09; // Named Export
export const formatCurrency = (val) => `$${val.toFixed(2)}`; // Named Export
export default class CartEngine {} // Default Export
JavaScript
// Consumer.js
import CartEngine, { TAX_RATE, formatCurrency } from './mathUtils.js';
Cheat Sheet Reference & Visuals
The premier modern interactive and open-source cheat sheets for modern JavaScript development are:
MDN Web Docs JavaScript Reference: The industry standard for official language specifications and browser compatibility tables.
Modern JavaScript Cheatsheet (mbeaudru on GitHub): Specifically tailored for developers moving to ES6+ and modern frameworks like React.
mbeaudru
/
modern-js-cheatsheet
Cheatsheet for the JavaScript knowledge you will frequently encounter in modern projects.
Modern JavaScript Cheatsheet

If you like this content, you can ping me or follow me on Twitter 👍
Introduction
Motivation
This document is a cheatsheet for JavaScript you will frequently encounter in modern projects and most contemporary sample code.
This guide is not intended to teach you JavaScript from the ground up, but to help developers with basic knowledge who may struggle to get familiar with modern codebases (or let's say to learn React for instance) because of the JavaScript concepts used.
Besides, I will sometimes provide personal tips that may be debatable but will take care to mention that it's a personal recommendation when I do so.
Note: Most of the concepts introduced here are coming from a JavaScript language update (ES2015, often called ES6). You can find new features added by this update here; it's very well done.
Complementary Resources
When you…
Cheatography JavaScript Sheet: Fast tabular references for array manipulations, regex syntax, and function helpers.

Top comments (0)