Skip to content
Happy Programming Guide
Start learning
JavaScript

JavaScript Basics

The syntax of JavaScript in one page: variables, types, operators, functions, conditions, loops, arrays, objects and the mistakes beginners make with each.

Books and a notebook on a desk

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#

JavaScript
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:

JavaScript
const scores = [1, 2, 3];
scores.push(4);        // fine - the array changed
scores = [5, 6];       // TypeError - the binding cannot change

Types#

JavaScript
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:

JavaScript
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#

JavaScript
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#

JavaScript
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#

JavaScript
// 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");
JavaScript
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#

JavaScript
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#

JavaScript
// 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:

JavaScript
const double = n => n * 2;         // returns
const double2 = n => { n * 2; };   // returns undefined

Arrays#

JavaScript
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#

JavaScript
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#

JavaScript
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#

JavaScript
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, in depthRead next

Keep reading

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *