This is the syntax half of JavaScript — variables, types, operators, functions, conditions, loops, and the two structures everything else is built from. Every section has a runnable example and a note about what commonly goes wrong. If you are wondering what JavaScript is for rather than how to write it, start with the introduction instead.
Variables#
const name = "Ana"; // cannot be reassigned
let count = 0; // can be reassigned
count = count + 1;
// var - old, avoid in new code
var old = "legacy";
Default to const. Use let only when you know the value will change. That habit makes reassignment visible, which is a genuine readability win.
const prevents reassignment, not modification:
const scores = [1, 2, 3];
scores.push(4); // fine - the array changed
scores = [5, 6]; // TypeError - the binding cannot change
Types#
const text = "hello"; // string
const number = 42; // number - integers and decimals alike
const flag = true; // boolean
const nothing = null; // deliberately empty
let notSet; // undefined - never assigned
const big = 9007199254740993n; // bigint
const key = Symbol("id"); // symbol
console.log(typeof text); // "string"
console.log(typeof null); // "object" - a well-known bug
console.log(Array.isArray([])); // true - the reliable array check
There is one number type. 1 and 1.5 are both numbers, and integer division gives you a decimal:
console.log(7 / 2); // 3.5
console.log(Math.floor(7 / 2)); // 3
console.log(0.1 + 0.2); // 0.30000000000000004
That last line is not a JavaScript flaw — it is how binary floating point works everywhere. For money, work in whole pence.
Strings#
const name = "Ana";
const age = 34;
// Template literals - the modern way
const message = "Hello " + name + ", you are " + age;
console.log(name.length); // 3
console.log(name.toUpperCase()); // ANA
console.log(name.includes("n")); // true
console.log(" padded ".trim()); // "padded"
console.log("a,b,c".split(",")); // ["a", "b", "c"]
console.log(name.at(-1)); // "a"
Template literals use backtick quotes and let you embed expressions directly, which is far more readable than concatenation once there is more than one value.
Comparison#
console.log(1 == "1"); // true - converts types first
console.log(1 === "1"); // false - compares type as well
console.log(null == undefined); // true
console.log(null === undefined); // false
Use === and !==. The loose versions apply conversion rules that are genuinely hard to predict, and the bugs they cause are hard to see.
Truthiness#
// Falsy: false, 0, -0, 0n, "", null, undefined, NaN
// Everything else is truthy - including "0", "false", [] and {}
if ([]) console.log("an empty array is truthy");
if ("0") console.log("the string zero is truthy");
const name = input || "Anonymous"; // any falsy value is replaced
const count = input ?? 0; // only null and undefined are replaced
Use ?? for defaults. With ||, a legitimate 0 or empty string gets silently replaced.
Conditions#
if (score >= 80) {
grade = "A";
} else if (score >= 70) {
grade = "B";
} else {
grade = "F";
}
const status = age >= 18 ? "adult" : "minor";
switch (command) {
case "start":
run();
break; // without break, execution falls through
case "stop":
halt();
break;
default:
console.log("unknown");
}
Functions#
// Declaration - hoisted, usable before it appears
function add(a, b) {
return a + b;
}
// Expression
const subtract = function (a, b) {
return a - b;
};
// Arrow function - shortest, and what you will see most
const multiply = (a, b) => a * b;
const square = n => n * n;
const greet = () => "hello";
// Defaults and rest parameters
function greetUser(name, greeting = "Hello") {
return greeting + ", " + name;
}
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
An arrow function with an expression body returns it automatically. With braces you must write return yourself:
const double = n => n * 2; // returns
const double2 = n => { n * 2; }; // returns undefined
Arrays#
const fruits = ["apple", "pear", "plum"];
fruits.push("fig");
fruits.length; // 4
fruits.at(-1); // "fig"
fruits.map(f => f.toUpperCase());
fruits.filter(f => f.length > 4);
fruits.find(f => f.startsWith("p"));
fruits.includes("pear");
[3, 1, 2].sort((a, b) => a - b); // numbers need a comparator
Objects#
const person = {
name: "Ana",
age: 34,
greet() {
return "Hello, " + this.name;
},
};
person.name; // dot notation
person["age"]; // bracket notation, for dynamic keys
person.city = "Leeds";
delete person.city;
const { name, age } = person; // destructuring
const copy = { ...person, age: 35 }; // copy with a change
Loops#
for (let i = 0; i < 5; i++) console.log(i);
for (const fruit of fruits) console.log(fruit); // values
for (const key in person) console.log(key); // keys - objects only
fruits.forEach((fruit, index) => console.log(index, fruit));
let n = 0;
while (n < 3) {
n++;
}
Errors#
try {
const data = JSON.parse(text);
console.log(data.name);
} catch (error) {
console.error("Could not parse:", error.message);
} finally {
console.log("done either way");
}
if (!Number.isFinite(value)) {
throw new Error("value must be a number");
}
Semicolons and strict mode#
JavaScript inserts semicolons automatically in most cases, so they are optional in practice. The safe advice is to pick one style and use a formatter such as Prettier so it is applied consistently.
Modules and class bodies are always in strict mode, which turns silent mistakes into errors. In a plain script, add "use strict"; at the top to get the same behaviour.
Questions people ask#
Should I use var at all?
No, in new code. It is function-scoped rather than block-scoped, which produces surprising behaviour inside loops and conditions. const and let exist because of it.
Why does adding arrays give a string?
[1] + [2] gives “12”, because + converts both to strings when it cannot add them as numbers. To join arrays use concat or the spread operator.
What is hoisting?
Function declarations and var bindings are moved to the top of their scope before the code runs, so they can be referenced earlier in the file. const and let are not usable before their declaration, which is safer.
Do I need semicolons?
Mostly not, but there are edge cases — a line starting with a bracket or parenthesis can join itself to the previous line. A formatter removes the question entirely.
Where to go next#
- Arrays and objects in JavaScript — both in depth.
- JavaScript array methods reference — every method with an example.
- Why is my JavaScript not working? — for the first errors you hit.