Data types
Meet JavaScript's seven primitive types and objects, learn what typeof really reports, and see why variables can hold different kinds of values over time.
- 01Tell primitives from objectsSay whether copying a value makes a separate copy, or makes two variables point to the same object.
- 02Name all eight JavaScript typesKnow string, number, bigint, boolean, undefined, symbol, null, and object when you see them.
- 03Use typeof wellRead what
typeofreally gives back, including its surprises fornull, arrays, functions, andNaN.
Watch the video lectures
Full course on YouTube (opens in a new tab) ↗- Lecture 10Primitive data types, part 1: numbers, strings, and booleansWatch on YouTube (opens in a new tab) ↗
- Lecture 11Primitive data types, part 2: undefined, null, BigInt, and SymbolWatch on YouTube (opens in a new tab) ↗
- Lecture 12Non-primitive data types: objectsWatch on YouTube (opens in a new tab) ↗
Values have types
Every value in JavaScript has a type. The type says what kind of value it is. For example, "Asha" is text, and 3 is a number.
The type also decides what you can do with the value. You can add two numbers. You can turn text into capital letters. The type belongs to the value, not to the variable. A variable is only a name that holds a value.
JavaScript has eight types. Seven of them are primitive types: one simple value, like 5 or "hi". The eighth type is object: a value that can hold other values inside it. You can't change a primitive; you can only replace it. You can change what is inside an object.
const user = "Asha";
const unreadCount = 3;
console.log(typeof user);
console.log(typeof unreadCount);Line 1 stores the text "Asha" in a variable called user. Line 2 stores the number 3 in a variable called unreadCount.
Lines 3 and 4 use typeof. It gives back the name of a value's type, as text. So line 3 prints string and line 4 prints number. "String" is JavaScript's word for text.
In Why JavaScript?, "5" + 3 gave "53". That happened because "5" is a string and 3 is a number. When you put a string and a number together with +, JavaScript joins them as text.
In the Variables: let, const & var lesson, you met two ways to change things:
- Reassignment: put a new value in a variable, like
b = 6. - Mutation: change something inside an object, like
box.n = 2.
The type of a value decides which of the two can happen. You'll see how in the next section. This lesson is a short tour of all eight types. Each type gets its own lesson later, starting with Numbers & math next.
Primitives vs objects
STEP THROUGHJavaScript values come in two families:
- A primitive is one simple value, like
5,"Ada",true, ornull. You can't change part of it. To get a different value, you replace it with a new one. - An object holds other values inside it, each under a name. Each named value is called a property. In
{ n: 1 }, the propertynholds1. Code can change properties.
The two families are also copied in different ways:
- A variable with a primitive holds the value itself. Copying it makes a second, separate value.
- A variable with an object holds a reference: a pointer that says where the object is. Copying it copies only the pointer. Then both variables point to the same object.
Think of a as a sticky note with 5 written on it. let b = a makes a second sticky note that also says 5. Writing 6 on the second note doesn't change the first note.
- In real life: A sticky note that says 5
- In JavaScript: A variable
athat holds the number5 - In real life: Copy the note onto a new note
- In JavaScript:
let b = acopies the number - In real life: Write 6 on the new note
- In JavaScript:
b = 6puts a new value inb - In real life: The first note still says 5
- In JavaScript:
ais still5
let b = a gives b its own copy of 5. Then b = 6 swaps only the card in b. The card in a still says 5.An object is like a house. A variable doesn't hold the house. It holds a card with the house's address. Copying the card doesn't build a second house. If someone paints the front door, everyone with that address sees the new color.
- In real life: A house
- In JavaScript: An object like
{ n: 1 } - In real life: A card with the house's address
- In JavaScript: A variable that points to the object
- In real life: Copy the address card
- In JavaScript:
const box2 = box1copies the reference - In real life: Paint the front door
- In JavaScript:
box2.n = 2changes the object, andbox1sees it too
const box2 = box1 copies only the reference, not the object. Both names point to the same object, so a change made through box2 shows up through box1 too.Guess both printed values first. Then step through: first a number is copied, then a reference to an object.
script
let b = a;b = 6;console.log(a); const box1 = { n: 1 };const box2 = box1;box2.n = 2;console.log(box1.n);Press Step to run the code one line at a time. Line 4 prints 5. Changing b didn't change a, because a number is a primitive, so b got its own copy.
Line 9 prints 2. box1 and box2 point to the same object, so the change on line 8 shows up through box1. Pick "Set n to 7", and line 9 prints 7 instead.
The lessons Objects & references and Memory: primitives vs objects go deeper. For now, remember one rule: copying a primitive copies the value. Copying an object variable copies the reference, so both variables point to one object.
const tea = "tea";
const loudTea = tea.toUpperCase();
console.log(tea);
console.log(loudTea);Line 1 stores the text "tea" in tea. Line 2 calls toUpperCase(), which gives back the same text in capital letters. It doesn't change tea. It makes a new string, "TEA", and line 2 stores it in loudTea.
Line 3 prints tea: the first string didn't change. Line 4 prints TEA.
This is what immutable means: a value that can't be changed. Every primitive is immutable. To get a different primitive, you make a new one and store it.
Most objects can be changed. Code can lock an object so its properties can't change, and some objects in the browser are read-only. But for the objects you make yourself, this rule holds: when two variables point to one object, a change made through one variable shows up through the other.
function isPrimitive(value) {
const valueType = typeof value;
return value === null || (valueType !== "object" && valueType !== "function");
}
console.log(isPrimitive("Asha"));
console.log(isPrimitive(["Asha"]));
console.log(isPrimitive(null));
console.log(isPrimitive(() => {}));Line 1 starts a function: a named set of steps you can run again and again. This one is called isPrimitive. It answers true or false.
- Line 2 saves the type name of
valueinvalueType. - Line 3 gives back
trueif the value isnull. It also gives backtrueif the type is not"object"and not"function". Here||means "or", and&&means "and". - Lines 6 to 9 try four values: text, a list,
null, and a function. They printtrue,false,true, andfalse.
null needs its own check on line 3, because typeof null gives "object". You'll see why in the next section.
The eight types
TABLEHere are all eight types. Seven of them are primitive types:
string: text, like"hi".number: a number, like42or3.14.bigint: a very large whole number. You write it with annat the end, like10n.boolean: yes or no. There are only two values,trueandfalse.undefined: no value yet.symbol: a one-of-a-kind ID, made withSymbol(). No two symbols are equal.null: empty on purpose.
The eighth type is object. Plain objects, arrays (lists of values), dates, functions, and Math are all objects.
object, is like a cart: it can hold other values inside it. Arrays and functions are objects too.A pantry is a food cupboard. Think of the eight types as eight shelves in it. You don't need to know every can on day one. You learn the shelf names, so you know where to look.
- In real life: A shelf for flour, a shelf for sugar
- In JavaScript: One type, like
numberorstring - In real life: A recipe asks for flour
- In JavaScript: Some code needs a certain type, like a number to add
- In real life: One shelf holds many bags of flour
- In JavaScript: One type holds many values:
1,2, and3.5are all numbers
The table below lists the eight types. Read each row as: "a value like this has this type, and typeof gives back this text."
| Type | Example value | What does typeof give? | What is it for? |
|---|---|---|---|
| string | "hi" | string | Text. The Strings lesson covers it. |
| number | 42 | number | Whole numbers and decimals, plus the special values NaN and Infinity. The next lesson, Numbers & math, covers it. |
| bigint | 10n | bigint | Whole numbers too big for the number type. The BigInt lesson covers it. |
| boolean | true | boolean | Yes or no: true or false. The Booleans, null & undefined lesson covers it. |
| undefined | undefined | undefined | No value yet. A variable you haven't given a value holds undefined. |
| symbol | Symbol("id") | symbol | A one-of-a-kind ID. No two symbols are equal. |
| null | null | object | Empty on purpose. typeof says object because of an old mistake in JavaScript. |
| object | {} | object | Plain objects, arrays, functions, dates, Math, and more. (typeof says function for functions.) |
Three rows need extra care:
nullis a primitive, buttypeof nullgives"object". This is an old mistake in JavaScript. It was never fixed, so that old websites keep working.- Functions are objects, but
typeofgives them their own answer,"function". - Arrays are objects too, so
typeofgives"object". To check for an array, useArray.isArray. You'll meet it soon.
const draftTitle = undefined;
const savedTitle = null;
console.log(draftTitle === undefined);
console.log(savedTitle === null);JavaScript has two values that mean "nothing here":
undefinedusually means no value was given yet.nullmeans "empty", and code chose it on purpose.
Line 1 stores undefined in draftTitle: a draft that has no title yet. Line 2 stores null in savedTitle: the title was cleared on purpose. Lines 3 and 4 use ===, which checks whether two values are exactly the same. Both lines print true.
Different apps use these two values in different ways. Follow what your app says each one means. typeof alone won't tell you.
42"text"truenullundefined10nSymbol()[1, 2]{ a: 1 }function () {}new Date()Math
Put each value in its family: primitive or object. After you sort a card, read its note.
The typeof operator
INTERACTIVEAn operator is a symbol or word that works on values, like +. typeof is an operator that asks for the name of a value's type. It gives back that name as a string, such as "number" or "object".
const value = null;console.log(typeof value);console.log(Array.isArray(value));For null, typeof gives "object". null is a primitive, but typeof gives object. This old mistake was never fixed, so that old websites keep working.
typeof on the value you pick. Line 1 changes to that value.Pick a value in the playground. Line 1 of the code changes to that value. The panel shows what real JavaScript says about it.
typeof is good for broad questions, like "is this a string?" It always gives one of these eight answers: "string", "number", "bigint", "boolean", "undefined", "symbol", "function", or "object". Four answers surprise people:
typeof nullis"object". This is the old mistake from the table. Whennullmatters, checkvalue === nullfirst.typeof []is"object", because arrays are objects. To check for an array, useArray.isArray(value).typeof function () {}is"function". Functions are objects you can call, andtypeofgives them their own answer. This one is useful.typeof NaNis"number".NaNmeans "Not a Number", but it is a special value of the number type. You get it when a math step fails, likeNumber("tea").
function describe(value) {
if (typeof value === "array") {
return "array";
}
return typeof value;
}
console.log(describe([1, 2]));This function should give back "array" for an array. Line 2 compares typeof value with "array". But typeof never gives "array", so line 2 is never true. Line 5 runs instead, and the program prints object. The fix is to use Array.isArray on line 2:
function describe(value) {
if (Array.isArray(value)) {
return "array";
}
return typeof value;
}
console.log(describe([1, 2]));Array.isArray(value) gives true for an array and false for everything else. Now line 2 is true, and the program prints array.
Check for the exact kind you need
typeof gives a first, rough answer. It says "object" for arrays and for plain objects alike. So when you need to know "is this an array?", ask that exact question with Array.isArray.
function describeList(value) {
if (value === null) return "No list yet";
if (!Array.isArray(value)) return "Not a list";
return value.length + " items";
}
console.log(describeList(["tea", "bread"]));
console.log(describeList(null));
console.log(describeList("tea"));The function describeList checks a value before it uses the value as a list:
- Line 2: if the value is
null, the list hasn't arrived yet. It gives back"No list yet". - Line 3: the
!means "not". If the value is not an array, it gives back"Not a list". - Line 4 runs only for an array.
value.lengthis the number of items in the array.
Lines 7 to 9 print 2 items, No list yet, and Not a list.
Pick the check that matches your question. Read each row of the table as: "to answer this question, write this check."
| Your question | The check to write | What does it tell apart? |
|---|---|---|
| Is this text? | typeof value === "string" | It tells strings apart from all other values. |
| Is this a list? | Array.isArray(value) | It tells arrays apart from other objects. |
| Was it left empty on purpose? | value === null | It tells null apart from all other values. |
| Can I call this? | typeof value === "function" | It tells functions apart from all other values. |
A profile page shows a user's name. Knowing "this is an object" is not enough. The page also needs a name property, and that name must be text.
function displayProfile(profile) {
if (profile === null || typeof profile !== "object" || Array.isArray(profile)) {
return "No profile";
}
if (typeof profile.name !== "string") {
return "Unknown user";
}
return profile.name;
}
console.log(displayProfile({ name: "Asha" }));
console.log(displayProfile({}));
console.log(displayProfile(null));- Lines 2 to 4 give back
"No profile"if the value isnull, is not an object, or is an array. Here!==means "is not exactly". - Lines 5 to 7 give back
"Unknown user"ifnameis not text. - Line 8 runs only when both checks pass. It gives back the name.
- Lines 10 to 12 print
Asha,Unknown user, andNo profile.
Do these checks where data comes into your code from outside, like from a form or a server. Knowing the type can't tell you that an object has every property your page needs, so check each property you use. When you made the value yourself a few lines earlier, you usually don't need the checks.
Dynamic typing
STEP THROUGHJavaScript is dynamically typed. This means a variable doesn't have a fixed type. A let variable can hold a number now, text later, and true after that. The type always belongs to the value the variable holds right now.
Picture a box with the name value written on it. The box name never changes. The thing inside has its own label that says what kind of thing it is. Put in 42, and the label says "number". Swap in "forty-two", and the label says "string".
- In real life: A box with the name value
- In JavaScript: The variable
value - In real life: The label on the thing inside
- In JavaScript: The type of the value
- In real life: Swap a toy for a book
- In JavaScript: Store a value of a different type
value, each time. Only the card inside changes. typeof value looks at the card that is in the box right now.Watch one variable hold a number, then text, then a boolean. Each typeof gives the type of the value inside right now.
script
console.log(typeof value);value = "forty-two";console.log(typeof value);value = true;console.log(typeof value);Press Step to run each line. Each typeof line prints the type of the value stored just before it: number, then string, then boolean.
Dynamic typing makes small programs quick to write. But you have to keep track of what kind of value your code expects. TypeScript, a later lesson, is a language built on top of JavaScript. In TypeScript you write down the type each variable should hold, and your editor warns you about mistakes before the program runs.
Watch out: a value can look like a number and still be text. If price holds "3", it holds a string, not the number 3. Clear variable names and small checks where data comes in help you spot this.
Where you’ll use this
You check types when your code gets a value from outside. For example:
- what a person typed into a form,
- a setting that was saved earlier,
- data sent to your page by a server.
The examples here are small, but real apps use the same checks.
function describeValue(value) {
if (Array.isArray(value)) return "array";
if (value === null) return "null";
return typeof value;
}
console.log(describeValue(["Ada", "Lin"]));
console.log(describeValue(null));Lines 2 and 3 handle the two values where typeof gives a confusing answer: arrays and null. Line 4 runs for every other value and gives back the typeof answer. Lines 7 and 8 print array and null. A later lesson, Checking types reliably, builds a fuller version.
function readQuantity(text) {
const quantity = Number(text);
if (text.trim() === "" || !Number.isFinite(quantity)) {
return "Enter a number";
}
return quantity;
}
console.log(readQuantity("3"));
console.log(readQuantity(""));
console.log(readQuantity("tea"));A form box always gives your code text, even when a person types a number. So 3 arrives as the string "3". The function readQuantity turns it into a number and checks it:
- Line 2:
Number(text)turns the text into a number.Number("3")gives3.Number("tea")givesNaN. - Line 3 checks two things.
text.trim()removes spaces from both ends of the text, sotext.trim() === ""is true for an empty box.Number.isFinite(quantity)is true only for a normal number, not forNaNorInfinity. The!in front means "not". - Line 4 gives back
"Enter a number"if the box was empty or the text wasn't a number. - Line 6 gives back the number.
Lines 9 to 11 print 3, Enter a number, and Enter a number. The empty check matters, because Number("") gives 0. Without it, an empty box would count as zero.
const original = { user: { name: "Asha" } };
const copy = { ...original };
copy.user.name = "Lin";
console.log(original.user.name);- Line 1 makes an object,
original. Its propertyuserholds another object. An object inside another object is called a nested object. - Line 2 uses spread syntax, the three dots
..., to copy the properties oforiginalinto a new object,copy. But it copies only the top level. Foruser, it copies the reference, not the object. This is called a shallow copy. - So
copy.userandoriginal.userpoint to the same object. Line 3 changes the name throughcopy. - Line 4 reads the name through
originaland printsLin.
A shallow copy is fine when the object has no objects inside it. If the inner objects must be separate too, copy them as well.
Common mix-ups
Each card below shows a common wrong idea, then what is really true.
"typeof tells me the exact kind of every value."
It gives only broad answers. Arrays, dates, and plain objects all give "object". When you need the exact kind, use a specific check like Array.isArray.
"null is an object."
null is a primitive. typeof null says "object" only because of an old mistake that JavaScript keeps.
"const makes an object unchangeable."
const only stops you from putting a new value in the variable. The object itself can still change: after const box = { n: 1 }, you can still write box.n = 2.
"Copying an object variable makes a new object."
It copies only the reference. Both variables point to the same object, until you make a real copy.
"NaN has its own type."
NaN is a value of the number type. It means a math step failed. It is not a ninth type.
"A value that looks like a number is a number."
Form input "3" is a string. Turn it into a number with Number(). Then check it with Number.isFinite when you need a normal number.
"{ ...object } copies everything inside an object."
Spread copies only the top level. Objects inside it are still shared until you copy them too.
Practice: spot the type
5 EXERCISESGuess the answer before you run any code. Start with the warm-ups. If you get stuck, open a hint.
Each line prints what typeof gives back for one value. Write the four printed lines in order.
console.log(typeof 42);
console.log(typeof null);
console.log(typeof [1, 2]);
console.log(typeof NaN);The lines print number, object, object, and number. typeof null gives object because of an old mistake. An array is an object. NaN is a value of the number type.
A profile page gets a list of users from an API: a service on a server that sends data to your page. The data might be an array, null, or some other value. Line 2 has a broken check. What should replace typeof value === "array" so that the function says "array" only for arrays?
function describe(value) {
if (typeof value === "array") {
return "array";
}
return typeof value;
}
console.log(describe([1, 2]));function describe(value) {
if (Array.isArray(value)) {
return "array";
}
return typeof value;
}
console.log(describe([1, 2]));Write Array.isArray(value) on line 2. It is true only for arrays, so the page won't mistake null or another object for a list.
Math is built into JavaScript. It holds math helpers like Math.round. Is Math a primitive or an object?
Math is an object. It holds numbers and functions as properties, such as Math.PI and Math.round.
What does line 4 print? Then explain in your own words why.
const box1 = { n: 1 };
const box2 = box1;
box2.n = 2;
console.log(box1.n);It prints 2. box1 and box2 point to the same object. So when line 3 changes box2.n, line 4 reads the same changed n through box1.
How many primitive types does JavaScript have? Try to name them all from memory first.
console.log(["string", "number", "bigint", "boolean", "undefined", "symbol", "null"].length);There are seven primitive types: string, number, bigint, boolean, undefined, symbol, and null. Object is the eighth type.
Quiz: check your understanding
7 QUESTIONSEach answer says why it is right or wrong. For a question with code, guess the output first, then choose.
Question 1 of 7Which sentence describes a primitive value?
Choose an answer to see the explanation.
Question 2 of 7This code copies a number into
b, then changesb. What does it print?Read the code, then predictlet a = 5; let b = a; b = 6; console.log(a);Choose an answer to see the explanation.
Question 3 of 7Which list holds only primitive types?
Choose an answer to see the explanation.
Question 4 of 7What does
typeof nullprint?Read the code, then predictconsole.log(typeof null);Choose an answer to see the explanation.
Question 5 of 7How should you check whether a value is an array?
Choose an answer to see the explanation.
Question 6 of 7The variable gets a number, then text. What does this print?
Read the code, then predictlet value = 42; value = "forty-two"; console.log(typeof value);Choose an answer to see the explanation.
Question 7 of 7What does
typeof NaNprint?Read the code, then predictconsole.log(typeof NaN);Choose an answer to see the explanation.
Key takeaways
- JavaScript has eight types: seven primitive types and the object type.
- You can't change a primitive; you can only replace it. Copying a primitive makes a separate value.
- Copying an object variable copies only the reference. Both variables then point to the same object.
typeofgives a type name as text. Remember its surprises:null, arrays, functions, andNaN.- A variable has no fixed type. The type belongs to the value it holds right now.
- Use
Array.isArrayto check for an array, andvalue === nullto check fornull. - A form always gives you text. Turn it into a number and check it before you use it as a number.
Remember the one-liner.
A value's type says what kind of value it is. The type decides how the value is copied, how you check it, and what you can do with it.
Coming next: Numbers & math.