DEV Community

Cover image for JavaScript Before React: Everything You Need to Know
Hamed Farazi
Hamed Farazi

Posted on

JavaScript Before React: Everything You Need to Know

1. Variables: var, let, and const

Variables allow us to store data.

JavaScript provides three ways to declare variables:

  • var
  • let
  • const

var

var is the older way of declaring variables.

var framework = "React";

console.log(framework);
// React
Enter fullscreen mode Exit fullscreen mode

However, var has some important problems.

For example, it is function-scoped rather than block-scoped.

if (true) {
  var framework = "React";
}

console.log(framework);
// React
Enter fullscreen mode Exit fullscreen mode

The variable escapes the if block.

This behavior can create unexpected bugs.

let

let allows you to declare variables that can be reassigned.

let age = 25;

age = 26;

console.log(age);
// 26
Enter fullscreen mode Exit fullscreen mode

Unlike var, let is block-scoped.

if (true) {
  let framework = "React";
}

console.log(framework);
// ReferenceError
Enter fullscreen mode Exit fullscreen mode

const

const declares a variable that cannot be reassigned.

const framework = "React";

framework = "Vue";
// TypeError
Enter fullscreen mode Exit fullscreen mode

However, const does not make objects immutable.

const user = {
  name: "Alice",
};

user.name = "Bob";

console.log(user.name);
// Bob
Enter fullscreen mode Exit fullscreen mode

The object can be modified because the reference remains the same.

But you cannot reassign the variable:

const user = {
  name: "Alice",
};

user = { name: "Bob" };
// TypeError
Enter fullscreen mode Exit fullscreen mode

Which one should you use?

In modern JavaScript:

  • Use const by default.
  • Use let when reassignment is necessary.
  • Avoid var in modern code.

You'll see const everywhere in React.


2. Data Types

JavaScript has several primitive data types.

const name = "Alice";       // String
const age = 25;             // Number
const isDeveloper = true;   // Boolean
const score = null;         // Null
let result;                 // Undefined
const id = Symbol("id");    // Symbol
const bigNumber = 123n;     // BigInt
Enter fullscreen mode Exit fullscreen mode

JavaScript also has objects.

const user = {
  name: "Alice",
  age: 25,
};
Enter fullscreen mode Exit fullscreen mode

Arrays are also objects in JavaScript.

const numbers = [1, 2, 3];

console.log(typeof numbers);
// "object"
Enter fullscreen mode Exit fullscreen mode

Understanding undefined vs. null

undefined usually means a value hasn't been assigned.

let username;

console.log(username);
// undefined
Enter fullscreen mode Exit fullscreen mode

null represents an intentionally empty value.

const selectedUser = null;
Enter fullscreen mode Exit fullscreen mode

One unusual JavaScript behavior:

console.log(typeof null);
// "object"
Enter fullscreen mode Exit fullscreen mode

This is a historical JavaScript quirk.


3. Operators and Comparisons

JavaScript supports arithmetic operators:

const a = 10;
const b = 3;

console.log(a + b); // 13
console.log(a - b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.333...
console.log(a % b); // 1
Enter fullscreen mode Exit fullscreen mode

Equality operators

Always understand the difference between == and ===.

console.log(5 == "5");
// true

console.log(5 === "5");
// false
Enter fullscreen mode Exit fullscreen mode

== performs type coercion.

=== compares values without performing that coercion.

Prefer === and !== in modern JavaScript.

Logical operators

const isLoggedIn = true;
const isAdmin = false;

console.log(isLoggedIn && isAdmin);
// false

console.log(isLoggedIn || isAdmin);
// true

console.log(!isLoggedIn);
// false
Enter fullscreen mode Exit fullscreen mode

These operators are particularly useful in React.


4. Truthy and Falsy Values

JavaScript doesn't always require a Boolean value in conditions.

Some values behave like true, while others behave like false.

Falsy values

The main falsy values are:

false
0
-0
0n
""
null
undefined
NaN
Enter fullscreen mode Exit fullscreen mode

Everything else is generally truthy, including empty arrays and empty objects.

console.log(Boolean([]));
// true

console.log(Boolean({}));
// true
Enter fullscreen mode Exit fullscreen mode

Example

const username = "";

if (username) {
  console.log("Username exists");
} else {
  console.log("Username is empty");
}
Enter fullscreen mode Exit fullscreen mode

This concept becomes extremely important when using conditional rendering in React.


5. Scope: Where Variables Exist

Scope determines where a variable can be accessed.

JavaScript has several important types of scope.

Global scope

const framework = "React";

function showFramework() {
  console.log(framework);
}

showFramework();
// React
Enter fullscreen mode Exit fullscreen mode

The function can access the global variable.

Function scope

function example() {
  const message = "Hello";

  console.log(message);
}

example();
// Hello

console.log(message);
// ReferenceError
Enter fullscreen mode Exit fullscreen mode

The variable exists only inside the function.

Block scope

if (true) {
  const message = "Hello";
  let framework = "React";
}

console.log(message);
// ReferenceError
Enter fullscreen mode Exit fullscreen mode

Variables declared with let and const are block-scoped.


6. Hoisting

Hoisting describes JavaScript's behavior of processing declarations before executing code.

It does not mean JavaScript physically moves your code.

var hoisting

console.log(framework);

var framework = "React";

// undefined
Enter fullscreen mode Exit fullscreen mode

The declaration is available, but the assignment hasn't happened yet.

Conceptually, this behaves similarly to:

var framework;

console.log(framework);

framework = "React";
Enter fullscreen mode Exit fullscreen mode

let and const

console.log(framework);

let framework = "React";
// ReferenceError
Enter fullscreen mode Exit fullscreen mode

Variables declared with let and const are also processed before execution, but they cannot be accessed before their declaration is initialized.

This period is called the Temporal Dead Zone (TDZ).

Function declarations

Function declarations can be called before their definition.

sayHello();

function sayHello() {
  console.log("Hello!");
}
Enter fullscreen mode Exit fullscreen mode

This works because function declarations are hoisted with their function definition.


7. Functions

Functions are reusable blocks of code.

Function declaration

function add(a, b) {
  return a + b;
}

console.log(add(5, 3));
// 8
Enter fullscreen mode Exit fullscreen mode

Function expression

const add = function (a, b) {
  return a + b;
};

console.log(add(5, 3));
// 8
Enter fullscreen mode Exit fullscreen mode

Arrow functions

Arrow functions are widely used in modern JavaScript and React.

const add = (a, b) => {
  return a + b;
};
Enter fullscreen mode Exit fullscreen mode

For a single expression, you can simplify the syntax:

const add = (a, b) => a + b;
Enter fullscreen mode Exit fullscreen mode

Single parameter

const square = number => number * number;

console.log(square(4));
// 16
Enter fullscreen mode Exit fullscreen mode

Returning an object

Remember to wrap the object in parentheses:

const createUser = (name) => ({
  name: name,
  active: true,
});

console.log(createUser("Alice"));
Enter fullscreen mode Exit fullscreen mode

Arrow functions and this

Arrow functions do not create their own this.

They inherit this from the surrounding lexical scope.

This is especially important when working with callbacks and React event handlers.


8. Callback Functions

A callback is a function passed into another function.

function greet(name, callback) {
  console.log(`Hello, ${name}`);

  callback();
}

function sayGoodbye() {
  console.log("Goodbye!");
}

greet("Alice", sayGoodbye);
Enter fullscreen mode Exit fullscreen mode

Output:

Hello, Alice
Goodbye!
Enter fullscreen mode Exit fullscreen mode

Callbacks are everywhere in JavaScript.

For example:

const numbers = [1, 2, 3];

numbers.map((number) => number * 2);
Enter fullscreen mode Exit fullscreen mode

The arrow function is a callback passed to map().

React uses callbacks for event handlers:

<button onClick={() => console.log("Clicked!")}>
  Click me
</button>
Enter fullscreen mode Exit fullscreen mode

9. Closures

A closure happens when a function remembers variables from its surrounding scope, even after that outer function has finished executing.

function createCounter() {
  let count = 0;

  return function () {
    count++;

    return count;
  };
}

const counter = createCounter();

console.log(counter());
// 1

console.log(counter());
// 2

console.log(counter());
// 3
Enter fullscreen mode Exit fullscreen mode

Why does this work?

The returned function still has access to the count variable from createCounter().

This is a closure.

Closures are fundamental to understanding many JavaScript patterns, including how React hooks preserve state between renders.


10. Arrays

Arrays store multiple values in a single variable.

const frameworks = ["React", "Vue", "Angular"];

console.log(frameworks[0]);
// React
Enter fullscreen mode Exit fullscreen mode

Important array methods

map()

Transforms every element.

const numbers = [1, 2, 3];

const doubled = numbers.map((number) => number * 2);

console.log(doubled);
// [2, 4, 6]
Enter fullscreen mode Exit fullscreen mode

filter()

Returns elements that satisfy a condition.

const numbers = [1, 2, 3, 4];

const evenNumbers = numbers.filter((number) => number % 2 === 0);

console.log(evenNumbers);
// [2, 4]
Enter fullscreen mode Exit fullscreen mode

find()

Returns the first matching element.

const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
];

const user = users.find((user) => user.id === 2);

console.log(user);
// { id: 2, name: "Bob" }
Enter fullscreen mode Exit fullscreen mode

reduce()

Accumulates values.

const numbers = [1, 2, 3, 4];

const total = numbers.reduce((sum, number) => sum + number, 0);

console.log(total);
// 10
Enter fullscreen mode Exit fullscreen mode

some() and every()

const numbers = [2, 4, 6];

console.log(numbers.some((number) => number > 5));
// true

console.log(numbers.every((number) => number % 2 === 0));
// true
Enter fullscreen mode Exit fullscreen mode

These methods are used constantly when working with API data and rendering lists in React.


11. Objects

Objects store data using key-value pairs.

const user = {
  name: "Alice",
  age: 25,
  role: "Frontend Developer",
};
Enter fullscreen mode Exit fullscreen mode

Access properties

console.log(user.name);
// Alice

console.log(user["age"]);
// 25
Enter fullscreen mode Exit fullscreen mode

Add properties

user.country = "Germany";
Enter fullscreen mode Exit fullscreen mode

Update properties

user.age = 26;
Enter fullscreen mode Exit fullscreen mode

Delete properties

delete user.role;
Enter fullscreen mode Exit fullscreen mode

Objects are essential for understanding React props, state, and API responses.


12. Destructuring

Destructuring allows you to extract values from arrays and objects.

Object destructuring

const user = {
  name: "Alice",
  age: 25,
  role: "Developer",
};

const { name, age } = user;

console.log(name);
// Alice

console.log(age);
// 25
Enter fullscreen mode Exit fullscreen mode

Rename properties

const { name: username } = user;

console.log(username);
// Alice
Enter fullscreen mode Exit fullscreen mode

Default values

const { country = "Unknown" } = user;

console.log(country);
// Unknown
Enter fullscreen mode Exit fullscreen mode

Array destructuring

const colors = ["red", "green", "blue"];

const [first, second] = colors;

console.log(first);
// red

console.log(second);
// green
Enter fullscreen mode Exit fullscreen mode

Destructuring in React

You'll frequently see this:

function UserProfile({ name, age }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>{age}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This is object destructuring applied to function parameters.


13. Spread Operator (...)

The spread operator expands values from arrays or objects.

Copy an array

const numbers = [1, 2, 3];

const copiedNumbers = [...numbers];

console.log(copiedNumbers);
// [1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

Combine arrays

const first = [1, 2];
const second = [3, 4];

const combined = [...first, ...second];

console.log(combined);
// [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

Copy and update an object

const user = {
  name: "Alice",
  age: 25,
};

const updatedUser = {
  ...user,
  age: 26,
};

console.log(updatedUser);
// { name: "Alice", age: 26 }
Enter fullscreen mode Exit fullscreen mode

Why is this important in React?

React state should generally be updated immutably.

Instead of modifying an existing object:

user.age = 26;
Enter fullscreen mode Exit fullscreen mode

You create a new object:

const updatedUser = {
  ...user,
  age: 26,
};
Enter fullscreen mode Exit fullscreen mode

This pattern is fundamental to React state updates.


14. Rest Parameters

The rest operator collects multiple arguments into an array.

function sum(...numbers) {
  return numbers.reduce((total, number) => total + number, 0);
}

console.log(sum(1, 2, 3, 4));
// 10
Enter fullscreen mode Exit fullscreen mode

The function can accept any number of arguments.

Rest in destructuring

const user = {
  name: "Alice",
  age: 25,
  country: "Germany",
};

const { name, ...otherDetails } = user;

console.log(name);
// Alice

console.log(otherDetails);
// { age: 25, country: "Germany" }
Enter fullscreen mode Exit fullscreen mode

Spread vs. Rest

They use the same syntax but serve different purposes.

  • Spread expands values.
  • Rest collects values.

15. Template Literals

Template literals allow you to create strings using backticks.

const name = "Alice";
const age = 25;

const message = `My name is ${name} and I'm ${age} years old.`;

console.log(message);
Enter fullscreen mode Exit fullscreen mode

Output:

My name is Alice and I'm 25 years old.
Enter fullscreen mode Exit fullscreen mode

You can also write multiline strings:

const message = `
  Hello!
  Welcome to JavaScript.
`;
Enter fullscreen mode Exit fullscreen mode

Template literals are useful when displaying dynamic content.


16. Optional Chaining (?.)

Optional chaining allows you to safely access properties that may not exist.

Imagine receiving this data:

const user = {
  name: "Alice",
  address: {
    city: "Berlin",
  },
};
Enter fullscreen mode Exit fullscreen mode

Without optional chaining:

console.log(user.address.city);
Enter fullscreen mode Exit fullscreen mode

But what if address doesn't exist?

const user = {
  name: "Alice",
};

console.log(user.address.city);
// TypeError
Enter fullscreen mode Exit fullscreen mode

Using optional chaining:

console.log(user.address?.city);
// undefined
Enter fullscreen mode Exit fullscreen mode

Multiple levels

const user = {};

console.log(user?.address?.city);
// undefined
Enter fullscreen mode Exit fullscreen mode

Optional function calls

user.onClick?.();
Enter fullscreen mode Exit fullscreen mode

This calls onClick only if it exists and is callable.

Optional chaining is particularly useful when working with API data.


17. Nullish Coalescing (??)

The nullish coalescing operator provides a default value when the left side is null or undefined.

const username = null;

const displayName = username ?? "Guest";

console.log(displayName);
// Guest
Enter fullscreen mode Exit fullscreen mode

Difference between || and ??

const count = 0;

console.log(count || 10);
// 10

console.log(count ?? 10);
// 0
Enter fullscreen mode Exit fullscreen mode

Why?

|| uses the fallback for any falsy value.

?? uses the fallback only for null or undefined.

This distinction matters when zero or an empty string is a valid value.


18. The Ternary Operator

The ternary operator is a concise way to write conditional expressions.

const age = 20;

const message = age >= 18 ? "Adult" : "Minor";

console.log(message);
// Adult
Enter fullscreen mode Exit fullscreen mode

The syntax:

condition ? valueIfTrue : valueIfFalse;
Enter fullscreen mode Exit fullscreen mode

React example

function LoginStatus({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? "Welcome back!" : "Please log in."}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This is one of the most common conditional rendering patterns in React.


19. Short-Circuit Evaluation

JavaScript logical operators can return values, not just Booleans.

Using &&

const isLoggedIn = true;

isLoggedIn && console.log("Welcome!");
Enter fullscreen mode Exit fullscreen mode

The second expression executes only when the first expression is truthy.

React example

function Notifications({ count }) {
  return (
    <div>
      {count > 0 && <p>You have {count} notifications.</p>}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Important React warning

Be careful when using numbers with &&.

function Notifications({ count }) {
  return (
    <div>
      {count && <p>You have notifications.</p>}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

If count is 0, React may render the number 0.

A safer version:

{count > 0 && <p>You have notifications.</p>}
Enter fullscreen mode Exit fullscreen mode

20. Modules: import and export

JavaScript modules allow you to split code into multiple files.

Export a function

// utils.js

export function add(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

Import the function

// main.js

import { add } from "./utils.js";

console.log(add(2, 3));
// 5
Enter fullscreen mode Exit fullscreen mode

Default exports

// User.js

export default function User() {
  return "Alice";
}
Enter fullscreen mode Exit fullscreen mode

Import it:

import User from "./User.js";
Enter fullscreen mode Exit fullscreen mode

Named vs. default exports

Named export:

export const name = "Alice";
Enter fullscreen mode Exit fullscreen mode

Import:

import { name } from "./user.js";
Enter fullscreen mode Exit fullscreen mode

Default export:

export default name;
Enter fullscreen mode Exit fullscreen mode

Import:

import username from "./user.js";
Enter fullscreen mode Exit fullscreen mode

Modules are fundamental to React applications because components are usually organized into separate files.


21. DOM Manipulation

The DOM (Document Object Model) represents the structure of an HTML document.

JavaScript can interact with the DOM.

Select an element

const heading = document.querySelector("h1");
Enter fullscreen mode Exit fullscreen mode

Change text

heading.textContent = "Hello JavaScript!";
Enter fullscreen mode Exit fullscreen mode

Add an event listener

const button = document.querySelector("button");

button.addEventListener("click", () => {
  console.log("Button clicked!");
});
Enter fullscreen mode Exit fullscreen mode

Example

<button id="counter">Click me</button>

<script>
  const button = document.querySelector("#counter");

  button.addEventListener("click", () => {
    button.textContent = "Clicked!";
  });
</script>
Enter fullscreen mode Exit fullscreen mode

What changes when you learn React?

In traditional JavaScript, you often manipulate the DOM directly.

In React, you usually describe what the UI should look like based on data and state.

Instead of manually changing elements, React manages UI updates for you.

This is one of the biggest conceptual differences between vanilla JavaScript and React.


22. Events

Events allow JavaScript to respond to user interactions.

Examples include:

  • click
  • input
  • submit
  • change
  • keydown

Vanilla JavaScript

const button = document.querySelector("button");

button.addEventListener("click", function () {
  console.log("Clicked!");
});
Enter fullscreen mode Exit fullscreen mode

React event handling

function App() {
  function handleClick() {
    console.log("Clicked!");
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Notice the difference:

  • Vanilla JavaScript uses addEventListener.
  • React uses event props such as onClick.

Also, React expects a function reference:

<button onClick={handleClick}>
  Click me
</button>
Enter fullscreen mode Exit fullscreen mode

Not an immediate function call:

<button onClick={handleClick()}>
  Click me
</button>
Enter fullscreen mode Exit fullscreen mode

The second version executes the function during rendering.


23. Promises

JavaScript often performs asynchronous operations.

Examples include:

  • Fetching API data.
  • Reading files.
  • Waiting for a timer.
  • Sending network requests.

A Promise represents the eventual completion or failure of an asynchronous operation.

A Promise can be:

  • Pending
  • Fulfilled
  • Rejected

Example

const promise = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve("Operation successful!");
  } else {
    reject("Something went wrong!");
  }
});
Enter fullscreen mode Exit fullscreen mode

Using .then()

promise
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });
Enter fullscreen mode Exit fullscreen mode

Promises are fundamental to working with APIs in React.


24. async and await

async and await make asynchronous JavaScript easier to read.

Using .then()

fetch("https://jsonplaceholder.typicode.com/users")
  .then((response) => response.json())
  .then((users) => {
    console.log(users);
  })
  .catch((error) => {
    console.error(error);
  });
Enter fullscreen mode Exit fullscreen mode

Using async and await

async function getUsers() {
  try {
    const response = await fetch(
      "https://jsonplaceholder.typicode.com/users"
    );

    const users = await response.json();

    console.log(users);
  } catch (error) {
    console.error(error);
  }
}

getUsers();
Enter fullscreen mode Exit fullscreen mode

Important details

  • async makes a function return a Promise.
  • await pauses that async function until the Promise settles.
  • try...catch helps handle errors.

await doesn't block the entire JavaScript application.

Example

async function getUser() {
  const response = await fetch(
    "https://jsonplaceholder.typicode.com/users/1"
  );

  const user = await response.json();

  return user;
}
Enter fullscreen mode Exit fullscreen mode

You'll use these concepts frequently when fetching data in React.


25. Fetch API

The Fetch API allows JavaScript to make HTTP requests.

GET request

async function getUsers() {
  const response = await fetch(
    "https://jsonplaceholder.typicode.com/users"
  );

  if (!response.ok) {
    throw new Error("Failed to fetch users");
  }

  const users = await response.json();

  return users;
}
Enter fullscreen mode Exit fullscreen mode

POST request

async function createUser() {
  const response = await fetch(
    "https://jsonplaceholder.typicode.com/users",
    {
      method: "POST",

      headers: {
        "Content-Type": "application/json",
      },

      body: JSON.stringify({
        name: "Alice",
        email: "alice@example.com",
      }),
    }
  );

  const user = await response.json();

  return user;
}
Enter fullscreen mode Exit fullscreen mode

Important

fetch() does not automatically reject the Promise for HTTP errors such as 404 or 500.

You should check:

response.ok
Enter fullscreen mode Exit fullscreen mode

This is important when handling API errors.


26. Error Handling

JavaScript uses try...catch to handle errors.

try {
  const result = riskyOperation();

  console.log(result);
} catch (error) {
  console.error("Something went wrong:", error);
}
Enter fullscreen mode Exit fullscreen mode

Example with asynchronous code

async function getData() {
  try {
    const response = await fetch("/api/data");

    if (!response.ok) {
      throw new Error("Request failed");
    }

    const data = await response.json();

    return data;
  } catch (error) {
    console.error(error);
  }
}
Enter fullscreen mode Exit fullscreen mode

Error handling is important when working with API requests and asynchronous operations.


27. Immutability

Immutability means creating new values rather than modifying existing ones.

JavaScript does not automatically make objects immutable.

Mutable example

const user = {
  name: "Alice",
  age: 25,
};

user.age = 26;
Enter fullscreen mode Exit fullscreen mode

The original object has been modified.

Immutable update

const user = {
  name: "Alice",
  age: 25,
};

const updatedUser = {
  ...user,
  age: 26,
};
Enter fullscreen mode Exit fullscreen mode

Now you have a new object.

Why does React care?

React state updates should generally replace objects or arrays with new references rather than mutate existing state.

For example:

const numbers = [1, 2, 3];

const updatedNumbers = [...numbers, 4];
Enter fullscreen mode Exit fullscreen mode

This creates a new array.

Understanding immutability will make React state much easier to understand.


28. Shallow Copy vs. Deep Copy

The spread operator creates a shallow copy.

const user = {
  name: "Alice",
  address: {
    city: "Berlin",
  },
};

const copiedUser = { ...user };
Enter fullscreen mode Exit fullscreen mode

The top-level object is copied, but the nested object is still shared.

copiedUser.address.city = "Paris";

console.log(user.address.city);
// Paris
Enter fullscreen mode Exit fullscreen mode

This happens because both objects reference the same nested object.

Using structuredClone()

For supported data types, you can create a deep copy:

const copiedUser = structuredClone(user);
Enter fullscreen mode Exit fullscreen mode

Now nested objects are copied too.

Note that structuredClone() has limitations and does not clone every possible JavaScript value, such as functions.


29. this Keyword

The this keyword refers to a context determined by how a function is called.

Object method

const user = {
  name: "Alice",

  greet() {
    console.log(`Hello, ${this.name}`);
  },
};

user.greet();
// Hello, Alice
Enter fullscreen mode Exit fullscreen mode

Here, this refers to the object before the dot.

Important

Arrow functions do not have their own this.

const user = {
  name: "Alice",

  greet: () => {
    console.log(this.name);
  },
};

user.greet();
Enter fullscreen mode Exit fullscreen mode

This does not behave like the previous example.

For object methods that need the object's this, use a regular method or function.

In React function components, you usually don't need to manually manage this, unlike older class-based React components.


30. Classes and Constructors

JavaScript supports class syntax.

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    return `Hello, ${this.name}`;
  }
}

const user = new User("Alice", 25);

console.log(user.greet());
// Hello, Alice
Enter fullscreen mode Exit fullscreen mode

Classes are useful to understand because JavaScript is a multi-paradigm language.

However, modern React primarily uses function components rather than class components.

You don't need to master classes before learning modern React.


31. Set and Map

JavaScript also provides built-in data structures.

Set

A Set stores unique values.

const numbers = new Set([1, 2, 2, 3, 3, 4]);

console.log(numbers);
// Set(4) { 1, 2, 3, 4 }
Enter fullscreen mode Exit fullscreen mode

Convert it into an array:

const uniqueNumbers = [...numbers];

console.log(uniqueNumbers);
// [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

Map

A Map stores key-value pairs.

const userRoles = new Map();

userRoles.set("Alice", "Admin");
userRoles.set("Bob", "User");

console.log(userRoles.get("Alice"));
// Admin
Enter fullscreen mode Exit fullscreen mode

Don't confuse:

  • Array.prototype.map() — transforms array elements.
  • Map — a separate JavaScript data structure.

32. Type Coercion

JavaScript sometimes converts values automatically.

This is called type coercion.

console.log("5" + 2);
// "52"
Enter fullscreen mode Exit fullscreen mode

The number becomes a string.

But:

console.log("5" - 2);
// 3
Enter fullscreen mode Exit fullscreen mode

Here, JavaScript converts the string to a number.

Explicit conversion

const number = Number("42");

console.log(number);
// 42
Enter fullscreen mode Exit fullscreen mode

Other useful conversions:

String(123);
Number("123");
Boolean(1);
Enter fullscreen mode Exit fullscreen mode

Understanding type coercion helps you avoid unexpected bugs.


33. JavaScript Execution and the Event Loop

JavaScript commonly runs code on a single main thread.

But it can handle asynchronous operations using browser or runtime APIs and the event loop.

Consider:

console.log("Start");

setTimeout(() => {
  console.log("Timeout");
}, 0);

console.log("End");
Enter fullscreen mode Exit fullscreen mode

Output:

Start
End
Timeout
Enter fullscreen mode Exit fullscreen mode

Even though the timer is set to 0 milliseconds, its callback doesn't execute immediately.

The callback runs later when the event loop allows it.

Promises and microtasks

console.log("Start");

setTimeout(() => {
  console.log("Timeout");
}, 0);

Promise.resolve().then(() => {
  console.log("Promise");
});

console.log("End");
Enter fullscreen mode Exit fullscreen mode

Output:

Start
End
Promise
Timeout
Enter fullscreen mode Exit fullscreen mode

Promise callbacks run as microtasks, which are processed before timer callbacks such as setTimeout().

You don't need to master every detail of the event loop before React, but understanding asynchronous execution is extremely helpful.


JavaScript Concepts You Should Master Before React

Here's a practical checklist.

Essential

  • [ ] let, const, and variable declarations
  • [ ] Primitive data types
  • [ ] Objects and arrays
  • [ ] Functions and arrow functions
  • [ ] Scope and closures
  • [ ] Destructuring
  • [ ] Spread and rest operators
  • [ ] Template literals
  • [ ] Array methods: map, filter, find, reduce
  • [ ] Conditional statements
  • [ ] Ternary operator
  • [ ] Logical operators
  • [ ] Modules: import and export
  • [ ] Promises
  • [ ] async and await
  • [ ] Fetch API
  • [ ] Error handling
  • [ ] Immutability

Helpful

  • [ ] Hoisting and Temporal Dead Zone
  • [ ] Optional chaining
  • [ ] Nullish coalescing
  • [ ] DOM manipulation
  • [ ] Event handling
  • [ ] this keyword
  • [ ] Classes
  • [ ] Set and Map
  • [ ] Event loop

Practice Projects Before React

Before starting React, try building these small projects using vanilla JavaScript.

1. Todo App

Practice:

  • Arrays
  • Objects
  • map()
  • filter()
  • DOM manipulation
  • Events

2. Weather App

Practice:

  • Fetch API
  • Promises
  • Async/Await
  • Error handling
  • API data

3. Shopping Cart

Practice:

  • Objects
  • Arrays
  • reduce()
  • Spread operator
  • Immutability

4. User Search

Practice:

  • filter()
  • includes()
  • Input events
  • Array manipulation

5. Counter

Practice:

  • Variables
  • Functions
  • Events
  • DOM updates

These projects will help you understand how JavaScript works before React introduces its own abstractions.


Final Thoughts

Learning React without understanding JavaScript is like trying to build a house without understanding the materials you're using.

You don't need to know every advanced JavaScript concept before starting React.

But you should feel comfortable with:

  • Functions
  • Objects
  • Arrays
  • Destructuring
  • Spread syntax
  • Array methods
  • Closures
  • Promises
  • Async/Await
  • Modules
  • Immutability

Once these concepts become familiar, React will feel much more natural.

Don't memorize JavaScript. Learn how to think in JavaScript.

React will come next.

Happy coding! 🚀

Top comments (0)