Topic 1.2
Primitive Types
In one line
JavaScript has seven primitive types (string, number, boolean, null, undefined, bigint and symbol) plus objects; typeof tells you a value's type, with a few famous quirks.
Think of it like this
Sorting things in a kitchen. Flour goes in the flour jar, eggs in the egg tray, milk in the fridge. You handle each kind differently: you can pour milk but not eggs. JavaScript sorts every value into a type the same way, and the type decides what you can do with it: you can add numbers, uppercase strings and say yes or no with booleans.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Type
- The kind of a value, like number or string. It decides what you can do with the value.
- Primitive
- A simple single value (string, number, boolean, null, undefined, bigint, symbol) that can't be changed in place.
- Object
- Any value that isn't a primitive: arrays, functions, dates and
{ }objects. It can hold many values. - undefined
- JavaScript's automatic "no value here".
- null
- A value you set on purpose to mean "empty".
- Operator
- A symbol or word that works on values, like
+,=ortypeof. - typeof
- An operator that returns a value's type as a string, like
"number". - Immutable
- Can't be changed after it's made. Every primitive is immutable.
- Reference
- A pointer to an object. Copying a reference shares the same object.
- Autoboxing
- JavaScript briefly wrapping a primitive in an object so you can call methods on it.
Step by step
01Meet the seven primitives
Each line below creates one primitive. You'll use the first five every day.
const name = "Asha"; // string
const age = 25; // number
const isMember = true; // boolean
let nickname; // undefined
const manager = null; // null
const stars = 1000000000000n; // bigint
const id = Symbol("id"); // symbol02Ask a value its type
typeof returns a lowercase string. Because it always returns a string, typeof typeof 42 is "string".
typeof "Asha" // "string"
typeof 25 // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof 10n // "bigint"03Learn the quirks
typeof null is "object" (a historic bug). To test for null, compare directly: value === null. Arrays are objects, so test them with Array.isArray. Functions get their own answer, "function".
typeof null // "object" (bug kept forever)
typeof [1, 2] // "object"
Array.isArray([1, 2]) // true
typeof function () {} // "function"04Copy by value vs copy by reference
Copying a primitive copies the value itself. Copying an object copies only the reference, so both names reach the same object.
05Methods on primitives
"cat".toUpperCase() works through autoboxing and returns a new string. The original stays "cat", which is why you must store the result: const loud = word.toUpperCase();.
Try it yourself
- 1
Predict the types
Before running the first example, add
console.log(typeof "42");andconsole.log(typeof 42n);. Write down your predictions, then run it. - 2
Break the sharing
In the third example, change
const q = p;toconst q = { n: p.n };. Predict whatp.nprints now, then run. Why is it different? - 3
Call a method on null
Add
console.log(nothing.length);at the end of the second example. Read the error in the console: which value has no properties?
Code & diagrams
Whole numbers and decimals share one type, `number`. And `null` reports `object`: that's the famous bug.
Console
(nothing was printed)Expected console output
string
number
number
boolean
undefined
object
bigint
symbolConsole
(nothing was printed)Expected console output
object
true
object
true
function
number
undefined
string`word.toUpperCase()` on its own line creates a new string and throws it away: strings never change in place.
Console
(nothing was printed)Expected console output
hi hi!
2
cat
CATSymbols arrived in ES2015 and `description` in ES2019; BigInt in ES2020. Topic 1.3 explains why such big numbers need BigInt.
Console
(nothing was printed)Expected console output
false
Symbol(id)
id
9007199254740994n
bigintBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Check for null with typeof
Write if (typeof user === "object") { console.log(user.name); } when user is null.
Break #2
Use a symbol in text
Write console.log("My id is " + Symbol("id"));
Myth vs fact
Myth
Everything in JavaScript is an object.
Fact
Primitives are not objects. They only behave like objects for a moment when you call a method on them (autoboxing). null and undefined don't even do that.
Myth
null is an object because typeof null says so.
Fact
null is a primitive. typeof null === "object" is a bug from 1995 kept for compatibility. A proposal to fix it was rejected because it broke real websites.
Myth
JavaScript has separate types for whole numbers and decimals.
Fact
There is one number type for both (64-bit floating point). bigint is a separate type only for very large whole numbers.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The
typeof nullbug comes from the first engine's value tags: values were stored with a type tag in their low bits, objects had tag 0, andnullwas the null pointer (all zero bits), so it read as an object. - ▸
typeof document.allis"undefined", even though it exists. It's a deliberate spec exception ([[IsHTMLDDA]]) so that very old browser-detection code keeps working. It's also the only falsy object. - ▸
Engines don't really create a wrapper object on every method call: V8 calls the method on the prototype (
String.prototype) directly. The wrapper is a spec model; the observable behaviour is the same. - ▸
new String("a")creates a real wrapper object:typeof new String("a")is"object"andnew String("a") === "a"isfalse. Never usenewwithString,NumberorBoolean; call them withoutnewto convert (Topic 1.5).
Remember this
- 1
A type is a kind of value. JavaScript has eight: seven primitive types and object. A primitive is a simple, single value with no parts you can change. They are: string (text, like
"hello"), number (any number, whole or decimal, like42or3.14), boolean (trueorfalse), undefined ("no value has been given"), null ("deliberately empty"), bigint (whole numbers of any size, written with ann:10n, added in ES2020) and symbol (a unique identifier, added in ES2015). Everything else, including arrays, functions and dates, is an object. - 2
undefinedandnullboth mean "nothing", but they are used differently.undefinedis what JavaScript gives you automatically: a variable with no value, a missing object property, a function that returns nothing.nullis what you write on purpose to say "empty for now", likelet selectedUser = null;before anyone is selected. A good habit: let JavaScript produceundefined, and usenullyourself. - 3
The
typeofoperator returns a string naming a value's type:typeof 42is"number",typeof "hi"is"string". An operator is a symbol or word that works on values, like+ortypeof. It has quirks you must know.typeof nullis"object": a bug from the very first version in 1995 that can never be fixed because old websites depend on it.typeofa function is"function", even though functions are objects.typeof [1, 2]is"object", so useArray.isArray(value)to detect arrays.typeof NaNis"number"(Topic 1.3). Andtypeofa name that was never declared gives"undefined"instead of throwing an error. - 4
Primitives are immutable: no operation changes a primitive value in place.
"cat".toUpperCase()doesn't change"cat"; it makes a new string"CAT". Primitives are also copied by value:let b = agivesbits own copy, so changingblater never affectsa. Objects are different:const q = pmakes both names point to the same object (a reference), so a change made throughqshows up throughp. - 5
How can a primitive have methods like
.toUpperCase()if it isn't an object? When you use a dot on a string, number, boolean, bigint or symbol, JavaScript briefly wraps it in a matching wrapper object (String,Number…), calls the method, and throws the wrapper away. This is called autoboxing.nullandundefinedhave no wrapper, which is whynull.lengththrows a TypeError. - 6
A symbol is a value guaranteed to be unique:
Symbol("id") === Symbol("id")isfalse. The text inside is only a description for debugging. Symbols are used as object keys that can never clash with other keys, and the language uses built-in ones such asSymbol.iterator(Topic 14.5). You'll rarely create them as a beginner, but you must recognise them.
Explain it without notes
Name JavaScript's primitive types. What makes a value primitive?
Why is typeof null equal to "object", and how do you correctly check for null and for arrays?
What is the difference between null and undefined?
How can "abc".length work if strings are not objects?
Practice
Log the type of each of these values: "", 0, false, [], {}, null.
Write two lines that prove strings are copied by value: copy a string into a second variable, change the second one, and log both.
Trade-offs
- ↔
Using both
nullandundefinedlets you tell "not set yet" from "deliberately empty", but it doubles the checks; many teams pick one (oftenundefined) for their own code and handle both at boundaries like APIs.
Done when you can
I can name all seven primitive types.
I can use
typeofand know its quirks withnull, arrays and functions.I can explain the difference between
nullandundefined.I can explain copy by value vs copy by reference.
I know why primitives can have methods.