Data Types
Every value in JavaScript belongs to a type. The language has seven primitive types plus objects, and that small list covers everything you'll work with — numbers, strings, booleans, arrays, dates, DOM nodes, promises, functions. Knowing what type a value is, and what category of type it belongs to, is the foundation of avoiding a whole class of bugs.
The seven primitives
string— text, e.g."hello"orhi, ${name}.number— 64-bit floats, includingNaNandInfinity. The same type covers42,-1,3.14and0.1 + 0.2.boolean—trueorfalse.undefined— the default value of declared-but-unassigned variables and missing function arguments.null— an intentional "nothing here yet" you assign on purpose.bigint— arbitrarily large integers, written with a trailingn:9007199254740993n.symbol— unique, hashable values often used as private object keys.
Everything else — arrays, plain objects, functions, dates, maps, regexes, DOM elements — is an object. That gives us our 8th category.
typeof — checking a value's type
The typeof operator returns a string describing the type of its operand.
typeof "hello"; // "string"
typeof 42; // "number"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof 10n; // "bigint"
typeof Symbol("id"); // "symbol"
typeof null; // "object" <- famous quirk
typeof []; // "object"
typeof {}; // "object"
typeof (() => {}); // "function" <- the one object subtype with its own labelA reference table
Quick reference
Category | Type | Example | typeof
-----------|-------------|----------------------|-------------
primitive | string | "hi" | "string"
primitive | number | 3.14, NaN, Infinity | "number"
primitive | boolean | true, false | "boolean"
primitive | undefined | undefined | "undefined"
primitive | null | null | "object" (!)
primitive | bigint | 9999999999999999n | "bigint"
primitive | symbol | Symbol("id") | "symbol"
object | plain obj | { a: 1 } | "object"
object | array | [1, 2, 3] | "object"
object | function | function () {} | "function"
object | date | new Date() | "object"
object | map/set | new Map(), new Set() | "object"
object | regex | /^a/ | "object"Primitives vs reference types
Primitives are immutable and copied by value. Objects are mutable and copied by reference. This single distinction explains a lot of surprising behaviour.
By value — primitives
let a = 5; let b = a; // b is a copy of the value b = 99; console.log(a, b); // 5 99 — changing b does NOT change a
By reference — objects
let user1 = { name: "Ada" };
let user2 = user1; // both point at the same object
user2.name = "Lin";
console.log(user1.name); // "Lin" — they're the same object!Lin
user1 and user2 are two variables holding the same reference. Mutating through one is visible through the other. To get an independent copy, clone the object.
Cloning an object (shallow)
const original = { name: "Ada", tags: ["admin"] };
const shallow = { ...original };
shallow.name = "Lin";
console.log(original.name); // "Ada" — safe
shallow.tags.push("vip");
console.log(original.tags); // ["admin", "vip"] — NOT safe — nested still sharedEquality and types
Two primitives with the same value are equal. Two objects are equal only if they are the same reference.
"hello" === "hello"; // true — same string value [1, 2] === [1, 2]; // false — two different arrays, different references const a = [1, 2]; const b = a; a === b; // true — same reference
Special numeric values
number covers everything from integers to floats. A few values are worth knowing:
Number.MAX_SAFE_INTEGER; // 9007199254740991
1 / 0; // Infinity
-1 / 0; // -Infinity
0 / 0; // NaN ("not a number")
NaN === NaN; // false (!)
Number.isNaN(NaN); // trueBeyond MAX_SAFE_INTEGER, ordinary numbers lose precision — reach for bigint. NaN is the only value that is not equal to itself, so always test it with Number.isNaN.
null vs undefined
Two values that mean "no value", with a soft convention:
undefinedis what JavaScript gives you when nothing is assigned yet: a missing function argument, an unset property, a return without a value.nullis what you assign to mean "intentionally empty". Functions that fail to find something often returnnull.
Wrapper objects
Primitives are not objects, but they act like objects when you use a method on them. The engine briefly wraps the primitive in a temporary object so you can call the method.
"hello".toUpperCase(); // "HELLO" (3.14).toFixed(1); // "3.1"
Avoid new String("x"), new Number(3), new Boolean(false) — they create actual objects, which are truthy and compare by reference. The shorter, primitive forms are what you want.