Frontend
Beginner 14 min read Frontend

JavaScript Core

JavaScript is the only language that runs natively in every browser. Master values, functions, closures, arrays and the event loop to build on in TypeScript and React.

JavaScriptECMAScriptclosuresevent loopasync/awaitV8
Prerequisites: HTML & CSS Basics
Introduction

What is this?

JavaScript is an interpreted, prototype-based language that runs natively in browsers and on servers through Node.js. It has first-class functions, closures, and a single-threaded, event-driven concurrency model. Modern ECMAScript adds arrow functions, template literals, destructuring and native modules.

Motivation

Why do you need it?

  • It is the only language browsers execute, so every interactive UI on the web depends on it.
  • First-class functions and closures enable powerful, composable patterns without extra syntax.
  • The single-threaded event loop makes concurrency predictable and easy to reason about.
  • Node.js and edge runtimes reuse the same language across server, build tooling and CLI scripts.
Think about it

Mental model

Imagine

A kitchen pass

Think of

The event loop

A single chef (one thread) handles orders one at a time but can start a long task like an oven and move on. When the timer rings, the chef returns to finish that order. JavaScript does the same with the task queue.

Mechanics

How it works

  • V8 and other engines parse source to bytecode, then JIT-compile hot paths to machine code for speed.
  • Values have types: primitives are immutable while objects are references stored in memory.
  • Functions are objects: they capture variables from the scope they were created in, forming closures.
  • The runtime runs a single-threaded loop: it executes the current task, drains the microtask queue, then pulls the next macrotask from the queue.
  • async/await desugars to Promises so I/O never blocks the one thread.

How the event loop processes synchronous and asynchronous work.

Script starts
Call stack
Web APIs / timers / fetch
Task queue
Microtasks
Loop continues
Reference

Key commands

node -v

Check the installed Node.js version.

v22.x.x
node script.js

Run a JavaScript file outside the browser.

node --watch script.js

Re-run the script whenever the file changes during development.

npm init -y

Create a package.json so you can install dependencies.

Wrote to package.json ...
npx eslint script.js

Lint the file and report unused variables, bugs and style issues.

node --inspect script.js

Open the inspector so Chrome DevTools can debug the script.

Hands-on

Examples

Fetch data and summarize it

Fetch data and summarize it
async function fetchUsers(url) {
const response = await fetch(url);
if (!response.ok) throw new Error("Request failed: " + response.status);
return response.json();
}
function summarize(users) {
const active = users
.filter((user) => user.active)
.map((user) => user.name.toUpperCase());
return active.length + " active users: " + active.join(", ");
}
fetchUsers("https://api.example.com/users")
.then((data) => console.log(summarize(data)))
.catch((err) => console.error(err.message));

await suspends the async function until fetch resolves without blocking the thread. filter and map transform the array immutably, and the promise chain handles both success and failure paths explicitly.

Real world

In production

  • Client-side interactivity: form validation, optimistic UI updates and rendering fetched data.
  • Server-side work on Node.js: APIs, background jobs and build tooling such as Vite and webpack.
  • The language powers edge functions on platforms like Vercel and Cloudflare Workers.
  • npm hosts over a million packages, so nearly every problem already has a maintained library.
Guidelines

Best practices

  • Use const by default and let only when you must reassign; avoid var.
  • Prefer strict equality (===) so type coercion does not mask bugs.
  • Write pure functions that take inputs and return outputs without mutating arguments.
  • Handle every promise rejection — unhandled rejections crash apps or silently lose errors.
  • Add JSDoc annotations or TypeScript types to functions with non-obvious contracts.
Watch out

Common mistakes

  • Forgetting await and logging a pending Promise instead of its resolved value.
  • Comparing with == and relying on coercion, producing false positives like 0 == ''.
  • Mutating arrays and objects in place, causing subtle aliasing bugs across components.
  • Writing blocking loops over huge data on the main thread, freezing the UI.
Root cause analysis

Common issues

Error
SyntaxError: Unexpected token '...'
Root cause

A syntax mistake, often a missing brace or comma, or an unclosed string.

Fix

Check the reported line and the line above it; use a linter or editor with syntax highlighting.

Error
Unhandled promise rejection
Root cause

A .then chain or try/catch does not cover every code path.

Fix

Add .catch to each chain or wrap await calls in try/catch.

Error
ReferenceError: X is not defined
Root cause

The variable was never declared, is scoped elsewhere, or the script loads before it is defined.

Fix

Declare X, move the code after its declaration, or check import paths.

When things break

Debugging tips

  • console.table prints arrays of objects as a readable grid; console.time labels performance segments.
  • Set breakpoints in DevTools Sources instead of scattering console.log everywhere.
  • Use the Network panel to confirm fetch requests and inspect status codes and payloads.
  • In Node, run with --watch and log structured data as JSON for easier grepping.
Interviews

Interview checkpoint

Practice

Hands-on lab

Build a CLI Task Lister
25 min · beginner
In progress
Objectives
  • Read command-line arguments in Node
  • Work with arrays and objects
  • Use async file I/O with promises
  • Handle errors gracefully

Build a CLI Task Lister

25 min · beginner

0/5 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/3
1

Which statement correctly creates an arrow function?

2

Unhandled promise rejections are safe to ignore in production.

3

Which operator performs a strict equality check that does not coerce types?

Quick reference

Cheat sheet

Modern syntax
const f = (x) => x * 2Arrow function
`Hello ${name}`Template literal
const { a, b } = objObject destructuring
const [...rest] = arrArray spread
const p = await fetch(url)Async/await
Array methods
arr.map(fn)Transform each element
arr.filter(fn)Keep matching elements
arr.reduce(fn, init)Fold to a single value
arr.find(fn)First match, or undefined
Go deeper

Official documentation