Values & Types — What JavaScript Actually Has
BeginnerJavaScript has seven primitive types and one object type. Everything that is not a primitive — arrays, functions, dates, regexes — is an object, and that single fact explains most surprising behaviour in the language.
Overview
Coming from Java you expect a rich type system enforced at compile time. JavaScript has neither: types exist at runtime, attach to values rather than variables, and a variable can hold anything. There are exactly seven primitives — string, number, boolean, null, undefined, symbol, bigint — and one composite type, object. Arrays are objects. Functions are objects that can be called. There is no separate int and float: every number is a 64-bit float, which is why 0.1 + 0.2 does not equal 0.3 and why integers above 2^53 lose precision. Understanding this small type list is what makes the rest of the language predictable rather than magical.
The Seven Primitives
Primitives are immutable and compared by value. Everything else is an object, compared by reference. typeof tells you which you have — with one historical bug that has never been fixed because too much code depends on it.
typeof 'hello' // 'string'
typeof 42 // 'number' — always a 64-bit float
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof Symbol('id') // 'symbol'
typeof 9007199254740993n // 'bigint'
typeof null // 'object' <-- the famous bug, from 1995
typeof [] // 'object' — arrays are objects
typeof function () {} // 'function' — objects you can call
// Reliable checks:
Array.isArray([]) // true
value === null // the only safe null check
Number.isInteger(42) // trueEvery Number Is a Float
There is no int. Every number is an IEEE 754 double, the same as Java's double. This is fine until you do money arithmetic or exceed the safe integer range, at which point it is quietly wrong rather than loudly wrong.
0.1 + 0.2 // 0.30000000000000004
0.1 + 0.2 === 0.3 // false
// Safe integer range: +/- 2^53 - 1
Number.MAX_SAFE_INTEGER // 9007199254740991
9007199254740992 === 9007199254740993 // true (!)
// For money: work in the smallest unit, as integers
const paise = 39999 // not 399.99
const display = (paise / 100).toFixed(2) // "399.99"
// For very large integers: BigInt
const big = 9007199254740993n
big + 1n // 9007199254740994nPrimitives vs References
Assigning a primitive copies the value. Assigning an object copies the reference. This is the same distinction Java makes between int and Object — but because JavaScript has no visible types, it catches people out far more often.
let a = 5
let b = a
b = 10
console.log(a) // 5 — unaffected
let x = { count: 5 }
let y = x
y.count = 10
console.log(x.count) // 10 — same object
// Copying an object, one level deep:
const copy = { ...x }
const arrCopy = [...someArray]
// Deep copy (structured clone, built into modern runtimes):
const deep = structuredClone(nested)Key Points to Remember
- 1Seven primitives — string, number, boolean, null, undefined, symbol, bigint — and everything else is an object
- 2Every number is a 64-bit float; there is no int, so 0.1 + 0.2 !== 0.3 and money belongs in integer paise
- 3typeof null returns "object" — a 1995 bug kept for compatibility; use value === null instead
- 4Primitives copy by value, objects copy by reference — the single most common source of "why did that change?"
- 5Spread copies one level deep; structuredClone() copies the whole tree
Interview Questions
Sign in to ask AriaWhy does 0.1 + 0.2 !== 0.3 in JavaScript?
What does typeof null return, and why?
How would you represent currency in a JavaScript application, and why not use a plain number?
Ask Aria about Values & Types — What JavaScript Actually Has
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.