JavaScript
The language of the web, and now of AI apps too.
JavaScript runs in every web browser and, through Node.js, on servers. It powers the chat interfaces, AI-powered websites and agent back ends that put models in front of billions of people.
Why learn JavaScript?
If you want people to use your AI, they will probably use it through a browser. JavaScript is the only language every browser runs natively, and the same language works on the server, so one language covers the whole app.
- Runs everywhere: browsers, servers, desktop apps (Electron) and mobile (React Native).
- AI in the browser: libraries like Transformers.js run models on the user's own device with WebGPU.
- First-class AI SDKs: OpenAI, Anthropic, Google and Vercel all publish JavaScript and TypeScript SDKs.
- The npm registry is the largest package collection in the world.
Set up and run your first program
You can start in any browser: press F12 and open the Console. For real projects, install Node.js (the LTS version) from nodejs.org, which also gives you npm for packages.
node --version
mkdir my-ai-app && cd my-ai-app
npm init -y
npm pkg set type=module # use modern import/exportconsole.log("Hello, AI!");
const name = "Ada";
console.log(`Welcome to JavaScript, ${name}.`);node hello.js. Setting "type": "module" in package.json lets you use import and top-level await.Variables and data types
Declare values with const (cannot be reassigned) or let (can change). Avoid the old var. The basic types are number, string, boolean, null, undefined, bigint and symbol; everything else is an object.
Template literals use backticks and ${} to insert values into text.
const model = "llama3.1"; // string
let tokens = 512; // number (all numbers are floating point)
const streaming = true; // boolean
let reply = null; // intentionally empty
let next; // undefined
tokens += 128;
console.log(typeof tokens); // "number"
console.log(`${model} can return ${tokens} tokens`);
console.log(Number("42") + 1); // 43
console.log("5" + 1, "5" - 1); // "51" and 4: watch out for type coercionDecisions and loops
if/else and switch choose a path. Use === (strict equality), never ==, to avoid surprising type conversions. for...of loops over values in arrays and strings.
const score = 0.82;
if (score >= 0.9) {
console.log("Excellent");
} else if (score >= 0.7) {
console.log("Good");
} else {
console.log("Keep training");
}
for (const gpu of ["H100", "B200"]) console.log(gpu);
for (let i = 0; i < 3; i++) console.log("step", i);
switch (process.platform) {
case "win32": console.log("Windows"); break;
case "darwin": console.log("macOS"); break;
default: console.log("Linux or other");
}Functions and closures
Functions are values: you can store them, pass them and return them. Arrow functions (=>) are the short modern form. A closure is a function that remembers variables from where it was created.
function accuracy(correct, total = 100) {
return (correct / total) * 100;
}
const double = (x) => x * 2;
function makeCounter() {
let count = 0; // remembered by the closure
return () => ++count;
}
const next = makeCounter();
next(); next();
console.log(next()); // 3
const apply = (fn, value) => fn(value);
console.log(apply(double, 21)); // 42
console.log(accuracy(45, 50)); // 90Arrays, objects, Map and Set
Arrays hold ordered lists and come with powerful methods: map, filter, reduce, find. Objects hold named properties. Map and Set are better when keys are not simple strings or values must be unique.
Destructuring and the spread operator ... unpack and copy data concisely.
const gpus = [
{ name: "RTX 4090", vram: 24 },
{ name: "H100", vram: 80 },
{ name: "MI300X", vram: 192 },
];
const big = gpus.filter((g) => g.vram >= 80).map((g) => g.name);
const total = gpus.reduce((sum, g) => sum + g.vram, 0);
console.log(big, total); // [ 'H100', 'MI300X' ] 296
const { name, vram } = gpus[1]; // destructuring
const copy = { ...gpus[0], vram: 32 };
const seen = new Set(["a", "b", "a"]); // Set { 'a', 'b' }
const cache = new Map([["prompt-1", "answer"]]);
console.log(name, vram, copy, seen.size, cache.get("prompt-1"));Classes and objects
Classes are a clear syntax over JavaScript's prototype system. Use constructor for set-up, extends to inherit, and # for truly private fields.
class Model {
#apiKey; // private field
constructor(name, params) {
this.name = name;
this.params = params;
this.#apiKey = "secret";
}
memoryGB(bytes = 2) { return this.params * bytes; }
static fromString(s) { const [n, p] = s.split(":"); return new Model(n, Number(p)); }
}
class ChatModel extends Model {
reply(text) { return `${this.name}: you said "${text}"`; }
}
const m = new ChatModel("Llama 3.1 8B", 8);
console.log(m.memoryGB(), m.reply("hi"));
console.log(Model.fromString("Qwen3:32").params); // 32Handling errors
Throw an Error (or your own subclass) when something goes wrong and catch it with try/catch. With async code, await inside try catches rejected promises too.
class OutOfMemory extends Error {}
function load(modelGB, vramGB) {
if (modelGB > vramGB) throw new OutOfMemory(`needs ${modelGB} GB`);
return "loaded";
}
try {
load(140, 24);
} catch (err) {
if (err instanceof OutOfMemory) console.log("Too big:", err.message);
else throw err;
} finally {
console.log("done");
}Modules and npm
ES modules split code into files with export and import. npm installs third-party packages into node_modules and records them in package.json.
// utils.js
export const toGB = (bytes) => bytes / 1e9;
export default function greet(name) { return `Hi ${name}`; }
// main.js
import greet, { toGB } from "./utils.js";
import { readFile } from "node:fs/promises"; // built-in Node module
console.log(greet("Ada"), toGB(8e9));
// terminal: npm install openai then import OpenAI from "openai";Files and JSON in Node.js
Node's fs/promises module reads and writes files without blocking. JSON.stringify and JSON.parse convert between objects and text.
import { readFile, writeFile } from "node:fs/promises";
const results = { model: "llama3.1", accuracy: 0.91 };
await writeFile("results.json", JSON.stringify(results, null, 2));
const data = JSON.parse(await readFile("results.json", "utf8"));
console.log(data.accuracy);Promises, async and await
JavaScript runs on a single thread with an event loop: slow tasks like network requests return a Promise and the program carries on. async/await lets you write that code in a readable top-to-bottom style. Promise.all runs several requests at once.
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
async function ask(model) {
await wait(1000); // stands in for a network call
return `${model} answered`;
}
const answers = await Promise.all([ask("a"), ask("b"), ask("c")]);
console.log(answers); // about 1 s in total, not 3 s
const res = await fetch("https://api.github.com/repos/pytorch/pytorch");
const repo = await res.json();
console.log(repo.stargazers_count);fetch is built into browsers and Node.js 18+, so you can call AI APIs without installing anything.JavaScript in the browser
In a web page, JavaScript reads and changes the page through the DOM and reacts to events such as clicks and key presses. This is how chat interfaces show messages as they stream in.
<input id="q" placeholder="Ask something">
<button id="send">Send</button>
<div id="out"></div>
<script type="module">
const out = document.querySelector("#out");
document.querySelector("#send").addEventListener("click", () => {
const p = document.createElement("p");
p.textContent = "You: " + document.querySelector("#q").value;
out.append(p);
});
</script>Testing and tools
Node has a built-in test runner (node --test). ESLint finds bugs, Prettier formats code, and many teams move to TypeScript for type checking as projects grow.
// utils.test.js (run with: node --test)
import { test } from "node:test";
import assert from "node:assert/strict";
import { toGB } from "./utils.js";
test("converts bytes to GB", () => {
assert.equal(toGB(2e9), 2);
});AI with JavaScript
JavaScript does AI in two ways. On the server, it calls model APIs and orchestrates agents. In the browser, it can run smaller models directly on the user's device using WebGPU or WebAssembly: private, offline and free to serve.
The essential libraries
Run a model in JavaScript with Transformers.js
This classifies the sentiment of a sentence. The model downloads once, then runs locally, in Node.js or in the browser.
// npm install @huggingface/transformers
import { pipeline } from "@huggingface/transformers";
const classify = await pipeline("sentiment-analysis");
const result = await classify("Tensor Cores make training so much faster!");
console.log(result); // [ { label: 'POSITIVE', score: 0.99... } ]Build an AI agent in JavaScript
The agent loop is the same in every language: send the conversation and your tool descriptions, run any tool the model asks for, send the result back, repeat. In JavaScript you need nothing but the built-in fetch.
const URL = "http://localhost:11434/v1/chat/completions";
const MODEL = "llama3.1";
const tools = {
get_weather: ({ city }) => `It is 24°C and sunny in ${city}.`,
};
const toolSpecs = [{
type: "function",
function: {
name: "get_weather",
description: "Get the current weather for a city",
parameters: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
},
},
}];
const messages = [{ role: "user", content: "Should I take an umbrella in Lahore today?" }];
while (true) {
const res = await fetch(URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ model: MODEL, messages, tools: toolSpecs }),
});
const msg = (await res.json()).choices[0].message;
messages.push(msg);
if (!msg.tool_calls?.length) { // final answer
console.log(msg.content);
break;
}
for (const call of msg.tool_calls) {
const args = JSON.parse(call.function.arguments);
const result = tools[call.function.name](args);
messages.push({ role: "tool", tool_call_id: call.id, content: result });
}
}To put this agent on a website, run it on your server (never expose API keys in the browser) and stream answers to the page. The Vercel AI SDK and the OpenAI Agents SDK for JavaScript package this pattern with streaming and memory.
ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.JavaScript learning roadmap
Tick items off as you go. Your progress is saved in this browser.
Beginner
Intermediate
Advanced
Projects to build
JavaScript cheat sheet
| Task | Syntax |
|---|---|
| Variable | const a = 1; let b = 2; |
| Template string | `Hi ${name}` |
| Strict equality | a === b |
| Arrow function | const f = (x) => x * 2; |
| Array methods | xs.map(f).filter(g) |
| Destructure | const { a, b } = obj; |
| Spread | const c = { ...obj, a: 3 }; |
| Optional chaining | user?.address?.city |
| Default value | value ?? "fallback" |
| Async function | async function f() { await g(); } |
| Fetch JSON | const d = await (await fetch(url)).json(); |
| Import | import { x } from "./x.js"; |
Common mistakes
- Using
==instead of===: loose equality converts types, so"0" == falseis true. - Forgetting
await: you get a Promise object instead of the value. - Putting API keys in front-end code: anyone can read them. Call AI APIs from your server.
- Changing arrays you are looping over: create a new array with
maporfilterinstead. - Floating-point surprises:
0.1 + 0.2is0.30000000000000004. Round when displaying money.
Where to go next
- MDN JavaScript Guide — the reference most developers use
- The Modern JavaScript Tutorial
- Learn Node.js
- Transformers.js documentation
On TensorCore.si: How AI works, LLM sampling simulator, AI Model Explorer.
Keyboard: [ previous language · ] next language · / search the library