JavaScript Syntax and Variables

let/const vs var, primitive types, template literals, arrays, objects, destructuring and spread/rest.

let, const, and why not var

Modern JavaScript declares variables with let (reassignable) or const (cannot be reassigned) — both are block-scoped, meaning they only exist inside the nearest enclosing { }:

Javascript
const name = "Ada";       // cannot be reassigned
let age = 30;             // can be reassigned
age = 31;                 // fine

if (true) {
  let scoped = "inside";
  console.log(scoped);    // "inside"
}
// console.log(scoped);   // ReferenceError: scoped is not defined

var, the original way to declare variables, is function-scoped, not block-scoped — it leaks out of if/for blocks, and it's hoisted with a confusing "declared but undefined" state, rather than raising a clear error like let/const do when accessed before declaration. There's essentially no reason to use var in modern code:

Javascript
if (true) {
  var leaked = "I escape the block";
}
console.log(leaked);   // "I escape the block" — surprising and error-prone

// let/const throw a clear error instead of silently giving `undefined`:
console.log(notYetDeclared);  // ReferenceError (the "temporal dead zone")
let notYetDeclared = 5;

Default to const. Only use let when you know the variable needs to be reassigned (a loop counter, an accumulator). This makes code easier to reason about — seeing const tells you immediately that a value never changes.

Primitive types

JavaScript has seven primitive types:

Javascript
const str = "hello";           // string
const num = 42;                // number (both integers and floats)
const big = 123456789012345678901234567890n;  // bigint (arbitrary precision integers)
const flag = true;             // boolean
const nothing = null;          // null — intentional "no value"
let notSet;                    // undefined — a declared variable with no assigned value
const id = Symbol("id");       // symbol — a guaranteed-unique value

console.log(typeof num);        // "number"
console.log(typeof notSet);     // "undefined"

null and undefined are both "empty," but mean different things: undefined is what JavaScript gives you automatically (an unset variable, a missing function argument, a nonexistent object property); null is a value you explicitly assign to say "this is intentionally empty."

Template literals

Backtick-delimited strings support embedded expressions and multi-line text — no more clunky + concatenation:

Javascript
const name = "Ada";
const age = 30;

const oldWay = "Hello, " + name + "! You are " + age + ".";
const modern = `Hello, ${name}! You are ${age}.`;

const multiLine = `Line one
Line two`;

Arrays

Javascript
const fruits = ["apple", "banana", "cherry"];

fruits.push("date");           // add to the end
console.log(fruits.length);    // 4
console.log(fruits[0]);        // "apple"
console.log(fruits.includes("banana"));  // true

const doubled = [1, 2, 3].map(n => n * 2);        // [2, 4, 6]
const evens = [1, 2, 3, 4].filter(n => n % 2 === 0);  // [2, 4]

Objects

Javascript
const user = {
  name: "Ada",
  age: 30,
  greet() {
    return `Hi, I'm ${this.name}`;
  },
};

console.log(user.name);        // "Ada" — dot access
console.log(user["age"]);      // 30    — bracket access (needed for dynamic keys)
user.email = "ada@example.com"; // adding a new property is just an assignment

Destructuring

Destructuring pulls values out of arrays or objects into individual variables in one expression:

Javascript
const point = [10, 20];
const [x, y] = point;
console.log(x, y);   // 10 20

const person = { name: "Ada", age: 30, city: "London" };
const { name, city } = person;      // pulls out matching keys by name
console.log(name, city);            // Ada London

const { age: userAge = 18 } = person;  // rename + default value

Spread and rest

The ... syntax means two different things depending on context: spreading an iterable out, or collecting multiple values in.

Javascript
// Spread — expand an array/object into individual elements
const nums = [1, 2, 3];
const combined = [...nums, 4, 5];        // [1, 2, 3, 4, 5]

const base = { a: 1, b: 2 };
const extended = { ...base, c: 3 };       // { a: 1, b: 2, c: 3 }

// Rest — collect remaining arguments/properties together
function sum(...numbers) {
  return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3, 4));            // 10

const { a, ...rest } = extended;
console.log(rest);                        // { b: 2, c: 3 }

Common mistakes

  • Reaching for var out of habit — its function-scoping and hoisting behavior cause bugs that simply don't exist with let/const.
  • Using == instead of ===== performs type coercion before comparing ("5" == 5 is true), which hides bugs. Always use ===/!== unless you have a specific, deliberate reason not to.
  • Forgetting that spreading an object ({ ...obj }) is a shallow copy — nested objects/arrays inside it are still shared references, not deep copies.

Interview questions

Q: Why is let/const preferred over var? let/const are block-scoped (matching how every other C-family language scopes variables), and accessing them before their declaration throws a clear error instead of silently returning undefined. var is function-scoped, leaks out of blocks like if and for, and its hoisting behavior is a frequent source of subtle bugs.

Q: What's the difference between null and undefined? undefined means a variable has been declared but never assigned a value, or a property/argument simply doesn't exist — it's JavaScript's own default "empty" marker. null is a value a developer explicitly assigns to represent "intentionally no value." null == undefined is true (loose equality treats them as equivalent), but null === undefined is false (they're different types).