Appearance
What JavaScript Actually Is
Open an unfamiliar JavaScript repository and you may see all of these on the first screen:
tsx
import { readFile } from "node:fs/promises";
import { useState } from "react";
interface User {
name: string;
}
export function UserCard({ user }: { user: User }) {
const [expanded, setExpanded] = useState(false);
return <button onClick={() => setExpanded(!expanded)}>{user.name}</button>;
}People casually call the whole thing “JavaScript,” but it is assembled from several layers:
import,export, functions, objects, and arrow functions are JavaScript.node:fs/promisesis a module supplied by Node.js.useStateis a function supplied by React.interfaceand the annotations after:are TypeScript.<button>...</button>is JSX syntax.- The click event and eventual button element belong to the browser platform and React's browser renderer.
Learning the ecosystem becomes much easier once you ask which layer owns each construct. That tells you where to find its documentation, whether it exists in another runtime, and whether it reaches the JavaScript engine unchanged.
The language is ECMAScript
JavaScript is standardized under the name ECMAScript. The specification defines the language's syntax and semantics: how expressions evaluate, how functions are called, how objects inherit, how promises settle, and how built-in values such as arrays and maps behave.
This is ordinary JavaScript:
js
const prices = [12, 7, 20];
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 39The language owns:
constdeclarations.- Array literals.
- Arrow functions.
- Property lookup for
prices.reduce. - The behavior of
Array.prototype.reduce. - Numbers and addition.
console, however, illustrates a boundary. Host environments expose a console API, and its exact presentation is not specified as part of the core language in the same way that Array.prototype.reduce is. Browsers and server runtimes provide compatible console objects because logging is universally useful.
ECMAScript also defines a module syntax:
js
// currency.js
export function formatUsd(amount) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount);
}js
// report.js
import { formatUsd } from "./currency.js";
console.log(formatUsd(19.5));The syntax and high-level module semantics are standardized, but a host still decides how a module specifier such as "./currency.js" is resolved and loaded. In a browser it starts as a URL relative to the importing module. In Node.js it resolves through Node's ECMAScript module loader.
JavaScript has no single standard library of filesystem, database, HTTP-server, or user-interface modules. Those capabilities come from hosts and libraries.
An engine executes the language
A JavaScript engine parses source code, creates the language's runtime values, and executes the program. Three important engines are:
- V8, used by Chromium and Node.js.
- JavaScriptCore, used by Safari and Bun.
- SpiderMonkey, used by Firefox.
Engine implementation matters for performance, diagnostics, debugging, and the schedule on which newly standardized features become available. It usually should not determine the architecture of ordinary application code.
An engine is not the same thing as a runtime. V8 by itself does not give a program Node's filesystem APIs, command-line arguments, or HTTP server. JavaScriptCore by itself is not Safari or Bun. A host embeds an engine and surrounds it with APIs and an execution environment.
A host makes JavaScript useful
Consider this browser program:
js
const button = document.querySelector("button");
button.addEventListener("click", () => {
document.body.classList.toggle("dark");
});Functions, constants, strings, property access, and the arrow callback are JavaScript. document, DOM elements, events, and CSS class manipulation are browser APIs.
Putting that file into an ordinary Node.js process fails at the first document access:
text
ReferenceError: document is not definedThe source is syntactically valid JavaScript. It fails because the selected host does not provide the global it expects.
Node.js supplies a different environment:
js
import { readFile } from "node:fs/promises";
const text = await readFile("notes.txt", "utf8");
console.log(text);Here, Promise and top-level await are language features. node:fs/promises is a Node-provided module whose functions communicate with the operating system.
Modern hosts deliberately share some APIs. Browsers, Node.js, Bun, and Deno all implement fetch, for example:
js
const response = await fetch("https://example.com/data.json");
const data = await response.json();That does not turn fetch into an ECMAScript built-in. It is a Web API adopted by multiple hosts. This distinction matters if you target an older runtime, a restricted embedded engine, or a testing environment that implements only part of the browser platform.
globalThis is the language-level way to refer to the host's global object without selecting a host-specific spelling:
js
console.log(globalThis.Array === Array); // trueIt does not make host APIs portable. globalThis.document is still absent in Node unless a library or test environment creates it.
Node.js, Bun, Deno, and browsers are environments, not dialects
Most JavaScript syntax works across modern environments. Differences arise primarily from:
- Available global objects and built-in modules.
- Module resolution.
- Security and permission models.
- TypeScript or JSX handling.
- Package installation conventions.
- Version support for recently added language features.
Node.js is the baseline runtime for this course because it makes the boundaries visible. Node supplies a runtime and standard modules; npm supplies package management; TypeScript, test runners, and bundlers are normally separate tools.
Bun combines more roles into one executable. Its current tooling includes a JavaScriptCore-based runtime, package manager, test runner, bundler, and on-the-fly support for TypeScript and JSX. A file such as index.ts can be run directly:
sh
bun run index.tsThat convenience does not mean TypeScript's static type system executes at runtime. Bun strips or transforms TypeScript syntax; type checking remains a separate concern. It also does not mean every Node package or subtle runtime behavior is identical.
Deno emphasizes Web-platform APIs, explicit permissions, and a cohesive built-in toolchain. It is useful to know that these alternatives exist, but switching runtimes before understanding the layers tends to hide rather than resolve confusion.
Libraries add values; frameworks establish conventions
Installing a package does not modify ECMAScript. It makes modules available to import:
js
import express from "express";
const app = express();
app.get("/health", (_request, response) => {
response.json({ ok: true });
});All the call and callback syntax is JavaScript. express, app.get, and response.json are library APIs. Express runs within a host—normally Node—and uses that host's networking facilities.
A framework usually goes further than a library by supplying structure and lifecycle conventions. React components are functions, but React decides when they are called, how state is associated with them, and how returned elements become UI. A full-stack React framework may additionally own routing, server rendering, bundling, data loading, and deployment integration.
When reading framework code, keep asking two questions:
- What would this expression mean as ordinary JavaScript?
- What additional meaning does the framework assign to the value or function?
For example:
jsx
function Greeting({ name }) {
return <h1>Hello, {name}</h1>;
}The function declaration and parameter destructuring are JavaScript. The JSX is transformed into JavaScript that describes an element. React treats the capitalized Greeting function as a component when that description is rendered.
TypeScript describes JavaScript without replacing it
TypeScript accepts JavaScript syntax and adds syntax for static types:
ts
function repeat(message: string, count: number): string {
return message.repeat(count);
}A typical emitted JavaScript version is conceptually:
js
function repeat(message, count) {
return message.repeat(count);
}The annotations help tooling check calls before execution, but JavaScript receives ordinary runtime values. If untyped external code calls repeat(null, "many"), the annotations are not present to reject those values at runtime.
This is why the course teaches JavaScript first. TypeScript models JavaScript's values, functions, objects, modules, and control flow. A strong model of the runtime makes TypeScript useful; a weak one encourages assertions that merely silence the checker.
JSX is syntax, not a browser language
Browsers do not generally parse JSX in ordinary JavaScript modules. Tooling transforms it:
jsx
const heading = <h1 className="title">Hello</h1>;With a modern React transform, that becomes calls into a JSX runtime. Other frameworks can use JSX with different runtime behavior. JSX and React are commonly paired, but neither is identical to the other.
TSX is simply the file context in which TypeScript syntax and JSX syntax are both accepted. It can contain several layers in one small expression, which is why learning to classify them is valuable.
A practical classification habit
When you encounter an unfamiliar name, work outward:
js
const controller = new AbortController();
const response = await fetch(url, { signal: controller.signal });- Is
newJavaScript syntax? Yes. - Is
AbortControllerdefined by ECMAScript? No; it is a Web API implemented by modern hosts. - Is
fetcha package import? Not here; it is a host global. - Does this run in every JavaScript environment? No; the target must implement both APIs.
For an imported name, follow the module specifier:
js
import { readFile } from "node:fs/promises"; // Node built-in
import { z } from "zod"; // Installed package
import { parseUser } from "./user.js"; // Local moduleThis habit scales from a ten-line script to a framework application. It prevents “JavaScript” from becoming an undifferentiated pile of syntax and tools.
The next article moves from the conceptual layers to the practical act of running a JavaScript program: files, the REPL, command-line input, packages, and the role of package.json.