Skip to content
JavaScript logo

JavaScript

First appeared 1995 · Brendan Eich

The only language that runs natively in every browser — and, since Node.js, on the server too.

Overview

JavaScript is a high-level, versatile programming language primarily used for web development. Created by Brendan Eich in 1995 while working at Netscape Communications, JavaScript allows developers to implement complex features on web pages, including dynamic content updates, interactive forms, animations, and client-server communication. Over the years, it has evolved into a full-fledged, multi-paradigm language capable of supporting object-oriented, functional, and event-driven programming. JavaScript is executed in web browsers but can also run on servers through environments like Node.js, making it essential for full-stack development. Its ecosystem includes countless libraries and frameworks such as React, Angular, and Vue.js for front-end development, and Express, NestJS, and Koa for back-end applications. JavaScript’s syntax is influenced by C and Java, while its dynamic typing and prototype-based object model give it great flexibility. Its asynchronous capabilities, event loops, and Promise-based handling of operations make it highly suitable for modern web applications. The language has become foundational to web technologies alongside HTML and CSS, and its popularity continues to grow due to its universal presence on the web, ease of use, and extensive developer community.

Key facts

The reference details, without the paragraph.

First appeared
1995
Designed by
Brendan Eich at Netscape
Typing
Dynamic and weak, with implicit coercion between types
Execution
Just-in-time compiled by engines such as V8, SpiderMonkey and JavaScriptCore
Memory model
Automatic — generational, mark-and-sweep garbage collection
Package manager
npm, pnpm, yarn or bun, backed by the npm registry
File extensions
.js, .mjs, .cjs
Standard
ECMAScript, with a new edition ratified each June
Concurrency
Single-threaded event loop, plus Web Workers for true parallelism
Licence
Open specification (ECMA-262); engines are individually open source

History

How the language got here — the decisions that still shape how you write it.

JavaScript was created by Brendan Eich at Netscape Communications in 1995, initially under the name Mocha, later renamed to LiveScript, and finally JavaScript to align with the marketing of Java, which was gaining popularity at the time. Eich developed the first version of JavaScript in just 10 days to provide web browsers with a lightweight, interpreted language that could enhance web pages with interactive functionality. JavaScript quickly became a standard for client-side scripting, enabling developers to manipulate the Document Object Model (DOM), handle events, and perform asynchronous operations via AJAX. Over the years, JavaScript evolved significantly, with the introduction of ECMAScript standards to formalize its syntax and features. ECMAScript editions such as ES5, ES6 (ES2015), and subsequent versions added classes, modules, arrow functions, template literals, async/await, and many other modern programming constructs. The rise of Node.js in 2009 allowed JavaScript to move beyond browsers and run on servers, making it a full-stack language and expanding its capabilities for enterprise and cloud applications. Modern JavaScript frameworks and libraries, including React, Angular, Vue.js, and Svelte, have revolutionized front-end development by enabling component-based architectures, reactive programming, and modular design patterns. JavaScript’s asynchronous programming model, event loop, and promise-based operations facilitate handling of I/O-intensive and real-time applications efficiently. The language continues to evolve with annual ECMAScript updates, ensuring it remains relevant, efficient, and aligned with modern software engineering practices. Its global community organizes conferences, maintains extensive documentation, and provides thousands of open-source tools, which support learning and development. JavaScript’s universality, flexibility, and active ecosystem make it indispensable for web developers, powering nearly every interactive feature on the web today.

  1. 1995

    Ten days in May

    Brendan Eich writes the first prototype at Netscape in about ten days. It is named LiveScript, then renamed JavaScript for marketing reasons — it has no technical relationship to Java, a confusion that has lasted thirty years.

  2. 1997

    ECMAScript standardised

    The language is handed to Ecma International so competing browsers can implement the same thing. The awkward name 'ECMAScript' exists because 'JavaScript' was a Sun trademark.

  3. 2005

    AJAX changes what a web page is

    Gmail and Google Maps show that a page can fetch data and update itself without reloading. JavaScript stops being a language for form validation and starts being a language for applications.

  4. 2008

    V8 and the JIT arms race

    Google ships Chrome with the V8 engine, which compiles JavaScript to machine code. Performance improves by an order of magnitude and makes everything that follows plausible.

  5. 2009

    Node.js puts JavaScript on the server

    Ryan Dahl wraps V8 in an event loop and a standard library. One language now spans both ends of a web application, and npm becomes the largest package registry in existence.

  6. 2015

    ES2015 (ES6) modernises the language

    `let`/`const`, arrow functions, classes, template literals, destructuring, promises and modules land together. This is the line between 'old JavaScript' and the language people write today.

  7. 2017

    async/await

    Asynchronous code finally reads top to bottom. Callback pyramids become a historical curiosity.

  8. 2020

    Optional chaining and nullish coalescing

    `?.` and `??` remove a large share of defensive boilerplate, and the annual release cadence settles into steady, incremental improvement.

  9. 2024

    The runtime field widens

    Deno and Bun push Node.js on startup speed, built-in TypeScript support and batteries-included tooling, while Node adopts a native test runner and a stable ESM story.

What it is good at

The reasons teams pick it, stated concretely.

  • It runs everywhere, with no install step

    Every browser on every device already executes JavaScript. No other language can be deployed to billions of machines by uploading a text file. That single fact explains most of its ecosystem's size.

  • One language across the whole stack

    Browser, server, build tooling, mobile via React Native, desktop via Electron, and edge functions all speak the same language. Shared validation code and shared types across a front end and back end remove an entire class of integration bug.

  • The largest package registry in existence

    npm hosts over three million packages. Whatever narrow problem you have, someone has published a solution — which is both the greatest strength and the source of the ecosystem's worst habits.

  • Genuinely fast for a dynamic language

    Modern JIT engines with inline caching and hidden classes make idiomatic JavaScript competitive with other managed runtimes. Numeric-heavy work can go further with typed arrays and WebAssembly.

  • First-class functions and closures

    Functions are values you can pass, return and capture state in. Callbacks, promises, middleware, hooks and functional array methods all fall out of that one design decision.

Trade-offs

Every language costs you something. Knowing what, before you commit, is the whole point.

  • Type coercion is genuinely surprising

    `[] + {}`, `'5' - 2`, and `NaN !== NaN` are the famous examples. The rules are consistent but rarely what you expect. Use `===`, avoid implicit conversion, and let a linter catch the rest.

  • Dependency sprawl and supply-chain risk

    A small application can pull in a thousand transitive packages from hundreds of maintainers. Audit what you add, prefer the standard library or a few well-maintained dependencies, and pin your lockfile.

  • Two module systems, still

    CommonJS (`require`) and ES modules (`import`) coexist uneasily. Most friction in Node tooling traces back to this split, though the situation improves with each release.

  • Framework churn

    The front-end tooling landscape turns over faster than any other ecosystem. Much of this is noise — the core language is stable and backwards compatible; it is the surrounding conventions that keep moving.

  • No static types out of the box

    At any real scale most teams reach for TypeScript. That is a sign of the gap, not a criticism — but it does mean 'plain JavaScript at scale' requires unusual discipline.

Code examples

Not syntax tours — the idioms that make code read like the language rather than a translation of another one.

Array methods replace most loops
const orders = [
  { id: 1, total: 30, status: 'paid' },
  { id: 2, total: 55, status: 'pending' },
  { id: 3, total: 12, status: 'paid' },
];

const paidRevenue = orders
  .filter((order) => order.status === 'paid')
  .reduce((sum, order) => sum + order.total, 0);

const byStatus = Object.groupBy(orders, (order) => order.status);

console.log(paidRevenue);        // 42
console.log(byStatus.paid.length); // 2
`filter`, `map` and `reduce` chain into a readable pipeline that says what you want rather than how to iterate. `Object.groupBy` is a recent addition that removes the reduce-into-an-object pattern everyone used to write by hand.
Destructuring and modern syntax
const config = { host: 'localhost', port: 8080, tls: { enabled: true } };

// Pull out what you need, with defaults and renaming.
const { host, port = 3000, tls: { enabled: tlsOn } } = config;

// Optional chaining and nullish coalescing survive missing data.
const timeout = config.network?.timeout ?? 5000;

// Spread copies shallowly and merges.
const production = { ...config, host: 'api.example.com' };

console.log(host, port, tlsOn, timeout);  // localhost 8080 true 5000
`??` differs from `||` in an important way: it only falls back on `null` or `undefined`, so a legitimate `0` or `''` is preserved. That distinction fixes a bug class that `||` quietly introduced for years.
async/await with proper error handling
async function loadUser(id) {
  const response = await fetch(`/api/users/${id}`);

  // fetch only rejects on network failure — a 404 is a resolved promise.
  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }
  return response.json();
}

// Run independent requests concurrently, not one after another.
const [user, settings] = await Promise.all([
  loadUser(1),
  fetch('/api/settings').then((r) => r.json()),
]);
Two things people get wrong: `fetch` does not throw on HTTP error statuses, so you must check `response.ok`; and awaiting in sequence when the requests are independent wastes time — `Promise.all` runs them together.
Closures capture state
function createRateLimiter(maxCalls, windowMs) {
  let calls = [];

  return function allow() {
    const now = Date.now();
    calls = calls.filter((time) => now - time < windowMs);
    if (calls.length >= maxCalls) return false;
    calls.push(now);
    return true;
  };
}

const limiter = createRateLimiter(2, 1000);
console.log(limiter(), limiter(), limiter());  // true true false
`calls` lives on after `createRateLimiter` returns, private to the returned function. This is the mechanism behind React hooks, Express middleware and most JavaScript module patterns.

Common pitfalls

The mistakes that cost everyone an afternoon at least once.

  • `==` versus `===`

    Loose equality applies coercion rules almost nobody remembers correctly — `'' == 0` is true, `null == undefined` is true, `null == 0` is false. Use `===` unless you specifically want the `null`/`undefined` check.

  • `this` depends on how a function is called

    Passing a method as a callback loses its receiver. Arrow functions capture `this` from the enclosing scope, which is why they are the right choice for callbacks and the wrong choice for object methods.

  • Forgetting `await` inside `map`

    `array.map(async x => ...)` returns an array of promises, not values. Wrap it: `await Promise.all(array.map(async x => ...))`.

  • Mutating shared objects

    Objects and arrays are passed by reference, and spread copies only one level deep. A nested object in a 'copy' is still the original — a frequent source of state bugs in UI code.

  • Floating point arithmetic

    `0.1 + 0.2 !== 0.3`. This is IEEE-754, not a JavaScript quirk, but it bites hardest here because there is no built-in decimal type. Use integer cents for money, or a decimal library.

  • Blocking the event loop

    A long synchronous loop freezes the entire page or stalls every request on a Node server. Break up heavy work, move it to a Web Worker, or hand it to a background job.

In production

Where it is running at scale, and what it is doing there.

  • Facebook (Meta)

    Frontend and backend development (React framework).

  • Google

    Frontend web applications, Angular framework, server-side with Node.js.

  • Netflix

    Frontend user interfaces, streaming apps.

  • PayPal

    Full-stack applications with Node.js and frontend web apps.

Learning path

A realistic order to learn things in, with something to build at each step.

  1. 1

    Days 1–7

    The language itself

    Values and types, `const` over `let` (never `var`), functions and arrow functions, arrays and objects, and strict equality. Run everything in the browser console — the feedback loop is instant.

    Build this: Build a page that takes a list of numbers and displays the total, average and largest.

  2. 2

    Weeks 2–3

    The browser

    The DOM, event listeners, `fetch`, and where JavaScript sits relative to HTML and CSS. Learn the event loop conceptually now — it explains why your code runs in an order you did not expect.

    Build this: Build a small app that fetches from a public API and renders the results, including loading and error states.

  3. 3

    Week 4

    Asynchrony properly

    Promises, `async`/`await`, `Promise.all` and `Promise.allSettled`, and error handling across await boundaries. This is where most beginners' mental model breaks; slow down here.

    Build this: Fetch from three endpoints concurrently and render whichever succeed, handling the failures gracefully.

  4. 4

    Months 2–3

    Tooling and one framework

    npm and lockfiles, ES modules, a bundler such as Vite, and one component framework — React, Vue or Svelte. Learn why the framework exists before learning its API.

    Build this: Rebuild your API app as a component-based project with a build step and deploy it.

  5. 5

    Ongoing

    Depth and safety

    TypeScript, testing with Vitest or Playwright, Node.js for the server side, and the runtime internals — prototypes, `this` binding, the microtask queue — that explain the odd behaviour you will eventually hit.

    Build this: Convert a project to TypeScript and add tests that would have caught a bug you actually shipped.

Ecosystem and tooling

The tools you will end up installing whichever project you join.

ToolWhat it does
Node.jsThe mainstream server-side runtime, with the largest ecosystem and deployment support
Deno / BunModern alternative runtimes with built-in TypeScript, test runners and faster startup
npm / pnpmPackage installation and lockfiles; pnpm saves significant disk space via a content-addressed store
ViteThe default build tool for new front-end projects — instant dev server, optimised production bundle
ESLintCatches the language's genuine footguns before they reach review
PrettierRemoves formatting from the list of things a team argues about
Vitest / PlaywrightFast unit testing and reliable cross-browser end-to-end testing
TypeScriptOptional static types layered on top; the default choice for teams and large codebases

JavaScript libraries

59 catalogued, each with installation, worked examples and best practices.

Frequently asked

Should I learn JavaScript or go straight to TypeScript?

Learn JavaScript's fundamentals first — TypeScript is JavaScript plus a type layer, and type errors are confusing when you are still unsure what the runtime does. A few weeks in, switch. Almost every professional codebase you will join is TypeScript.

Is JavaScript really single-threaded?

Your code runs on one thread, but the runtime does not. Network requests, timers and file I/O are handled outside that thread and queue their callbacks back onto it. For genuine CPU parallelism, use Web Workers in the browser or `worker_threads` in Node.

React, Vue, Svelte or none?

For a page with a handful of interactive pieces, plain JavaScript is fine and much simpler. For an application with meaningful shared state, pick one: React has the largest job market and ecosystem, Vue is the gentlest to learn, Svelte produces the least code. The underlying concepts transfer between all three.

Node, Deno or Bun?

Node.js for anything with production or hiring constraints — the ecosystem and deployment support are unmatched. Bun for speed-sensitive tooling and scripts. Deno when you want TypeScript, a test runner and a permissions model with no configuration at all.

Is jQuery still relevant?

For new code, no. `querySelector`, `fetch`, `classList` and template literals cover what jQuery was invented to smooth over. It remains on a large share of existing sites, so you will still read it — but there is no reason to reach for it today.

How do I keep npm dependencies under control?

Commit your lockfile, run `npm audit` in CI, prefer packages with recent commits and few dependencies of their own, and ask whether ten lines of your own code would do instead. Every dependency is code you are responsible for but did not write.