Booleans, null & undefined
Learn true, false, JavaScript’s eight falsy values, and the difference between intentional null and not-yet-filled undefined.
- 01Tell truthy from falsyName the eight falsy values, and explain why values like
[]are truthy. - 02Tell null from undefinedUse
nullfor "empty on purpose" and know when JavaScript givesundefined. - 03Check for missing values safelyWrite checks that don't treat
0or""as missing.
Yes, no, and no value
Programs often need a plain yes or no. Is the menu open? Did the user fill in the form? Should this message show? JavaScript has two values for this, called booleans:
truemeans yes.falsemeans no.
const subscribed = true;const muted = false;console.log(subscribed);console.log(muted);Line 1 stores true in subscribed. Line 2 stores false in muted. Lines 3 and 4 print them. These are real booleans, not the text "true" or "false".
Most of the time you don't type true yourself. You ask a question, and JavaScript answers with a boolean. A comparison, like 3 >= 2, is one such question.
const hasEnoughTea = 3 >= 2;const hasEnoughMilk = 1 >= 2; console.log(hasEnoughTea);console.log(hasEnoughMilk);Line 1 asks "is 3 at least 2?" The answer is yes, so hasEnoughTea holds true. Line 2 asks "is 1 at least 2?" The answer is no, so hasEnoughMilk holds false. Lines 4 and 5 print true, then false. A name like hasEnoughTea reads like a question. That makes the code easy to read later.
This lesson also looks at two other values: null and undefined. They are not booleans. But they often show up next to yes/no checks, because code must also ask, "Do I have a value at all?" Each of the three has its own lesson:
Here you put them side by side and learn which check to use for each job.
- A boolean is one of two values:
trueorfalse. - A truthy value is any value that an
iftreats liketrue. - A falsy value is any value that an
iftreats likefalse. nullmeans "empty on purpose". Code puts it there.undefinedmeans "no value was given yet".
A guard at a party has a short no list with a few names on it. People on the list stay out. Everyone else gets in. The guard only checks the list. A name tag that says "false" still gets in, because that name is not on the list.
- In real life: The few names on the no list
- In JavaScript: The eight falsy values
- In real life: Everyone else gets in
- In JavaScript: Every other value is truthy
- In real life: A name tag that says "false"
- In JavaScript: The string
"false"is truthy
This lesson uses tiny if statements, because they show truthiness most clearly. An if runs its code only when its condition counts as yes. You'll learn if fully in a later lesson. For now, read if (value) as "if this value counts as true".
Truthy and falsy values
INTERACTIVEThe condition of an if does not have to be true or false. It can be any value. JavaScript first turns the value into a boolean, then decides. Only eight values turn into false. They are the falsy values, and the list is short enough to learn by heart:
false0, the number zero-0, negative zero0n, zero as a BigInt (a whole-number type you'll meet in the next lesson)"", the empty string (text with no characters)nullundefinedNaN, which means "not a number"
Every other value is truthy. That includes values that look empty or false: "0", "false", " ", [], , -1, and Infinity.
if treats these eight values like false. The right side shows values that only look empty or false. They are not on the list, so they are truthy.So if (value) is handy for asking "is there something here?" But be careful when 0 or an empty string is a real answer. The check treats them as "nothing".
const price = Number("tea"); console.log(Number.isNaN(price));console.log(Boolean(price));Line 1 asks Number("tea") to turn the text "tea" into a number. It can't, so it gives NaN. Line 3 uses Number.isNaN(price), which asks "is this NaN?" It prints true. Line 4 prints false, because NaN is falsy.
A falsy check only tells you "this counts as no". It can't tell NaN apart from 0 or null. When you need to know that a number failed, use Number.isNaN.
false0-00n""nullundefinedNaN"0""false"" "[]{}-1Infinity
Put each value on the side where it belongs. Only the eight values on the falsy list are falsy.
Test truthiness for real
PLAYGROUNDPick a value. The code below tests it in three ways, and all three always agree:
Boolean(value)turns the value intotrueorfalse.!!valuedoes the same thing. One!gives the opposite boolean. A second!flips it back.if (value)runs the truthy branch or the falsy branch. A branch is the block of code that runs.
const value = false;console.log(Boolean(value));console.log(!!value);if (value) { console.log("truthy branch");} else { console.log("falsy branch");}false is falsy. Boolean(value) gives false, !!value gives false, and the if statement runs the falsy branch. false is the boolean that means no.
Try [] and . An empty array is still an array, and an empty object is still an object. Every array and object is truthy, even with nothing inside. To ask "does this list have items?", check its length, the number of items. Don't test the array itself.
null vs undefined
COMPAREnull and undefined both mean "there is no useful value here". But they mean it in different ways:
nullmeans the value is empty on purpose. Some code chose to putnullthere.undefinedmeans no value was given yet. Usually JavaScript gives youundefinedby itself.
Think of a profile form. You click "Remove photo", and the photo field is now empty because you chose that. Another field, "Nickname", is empty because nobody has typed anything there yet. Both fields are empty, for two different reasons.
- In real life: You clear the field on purpose
- In JavaScript: Your code stores
null - In real life: Nobody has filled in the field yet
- In JavaScript: A missing property or argument is
undefined - In real life: The cleared field tells others you chose empty
- In JavaScript:
nullshows a choice
null in the box on purpose. On the right, the code never put anything in, so JavaScript gives undefined.The table compares the two values. Read each row as a question, then the answer for null and for undefined.
| Question | null | undefined |
|---|---|---|
| What does it mean? | The value is empty on purpose. | No value was given yet. |
| Who usually puts it there? | Your code, or a tool that tells you it found nothing. | JavaScript, when a value is missing. |
What does typeof give? | "object". This is an old mistake in JavaScript. | "undefined". |
Does loose equals == call them equal? | Yes. null == undefined is true. | Yes. undefined == null is true. |
Does strict equals === call them equal? | No. null === undefined is false. | No. undefined === null is false. |
What does JSON.stringify do with it inside an object? | It keeps it as null. | It leaves the property out. |
You saw typeof null in the Data types lesson. typeof tells you the type of a value, and for null it gives "object". This is an old mistake that was never fixed. null is not an object, and you can't read properties from it.
const profile = { nickname: undefined, photoUrl: null,}; console.log("nickname" in profile);console.log(profile.nickname === undefined);console.log("age" in profile);console.log(profile.age === undefined);console.log(profile.photoUrl === null);Lines 1 to 4 make a profile object. It has a nickname property that holds undefined, and a photoUrl property that holds null. It has no age property at all.
The in operator asks "does this object have a property with this name?" Line 6 prints true: nickname is there, even though its value is undefined. Line 8 prints false: age was never added. But lines 7 and 9 both print true, because reading nickname or age gives undefined either way. So reading a property can't tell you whether it is there. Use in for that.
const profile = { nickname: undefined,}; console.log(Object.hasOwn(profile, "nickname"));console.log(Object.hasOwn(profile, "age"));Object.hasOwn(profile, "nickname") asks the same question in another way: "does profile itself have a property called nickname?" Line 5 prints true, and line 6 prints false. For plain data, like data from a form or a server, Object.hasOwn is often the clearer choice.
const profile = { nickname: undefined, photoUrl: null,}; console.log(JSON.stringify(profile));console.log(JSON.stringify([undefined, null]));console.log(JSON.stringify(undefined));JSON is a text format for sending data, for example to a server. JSON.stringify turns a value into JSON text. Here is what each line prints:
- Line 6 prints
{"photoUrl":null}. JSON keeps a property that holdsnull, but leaves out a property that holdsundefined. - Line 7 prints
[null,null]. An array must keep every position, so JSON writesundefinedasnullthere. - Line 8 prints
undefined. There is no JSON text forundefinedon its own, so the call gives backundefinedinstead of text.
function greeting(name = "friend") { return "Hi, " + name;} console.log(greeting());console.log(greeting(null));On line 1, name = "friend" is a default value. It is used when the caller gives no name. Line 5 calls greeting() with nothing, so name is undefined, the default fills in, and it prints "Hi, friend". Line 6 passes null. A default value only fills in for undefined, so it prints "Hi, null". If null should get "friend" too, use ?? inside the function. You'll meet ?? later in this lesson.
Where missing values appear
STEP THROUGHYou get undefined in many everyday places. Here are five of them:
- a variable made with
letbut given no value, - an object property that doesn't exist,
- a function that has no
return, - a function argument the caller left out,
- an array position past the end of the array.
null shows up when code puts it there on purpose. Some browser tools also give null when they find nothing. For example, document.querySelector(".missing") searches the page for an element. When nothing matches, it gives null. In the Talking to the user lesson, prompt also gives null when the user clicks Cancel.
Step through the code below. Watch each line make an undefined, and the last one make a null.
Step through five everyday ways to get undefined, then one null that the code chose on purpose.
script
const profile = { name: "Ada" };function noReturn() { const message = "done";}function echo(nickname) { return nickname;}const list = ["first"];const deliberatelyEmpty = null; console.log(notFilled);console.log(profile.age);console.log(noReturn());console.log(echo());console.log(list[3]);console.log(deliberatelyEmpty);const todos = ["tea", "milk"];const missingTodo = todos.find((todo) => todo === "bread"); console.log(missingTodo);Line 1 makes a list of two to-dos. On line 2, find looks for the item "bread". It isn't in the list, and find gives undefined when nothing matches. So line 4 prints undefined. Other tools, like querySelector, give null instead. Don't guess. Look up what a tool gives when it finds nothing, then write a check for that value.
Checking for missing values
STEP THROUGHA common beginner bug is to treat "falsy" as if it meant "missing". Say a quantity can be 0, or a name can be an empty string. Then if (value) catches too much: it treats 0 and "" as missing too.
The step-through below runs four checks on the same value. Pick a value, then step through the lines:
- Line 2,
Boolean(name), is the truthy check. - Line 3,
name === undefined, istrueonly forundefined. - Line 4,
name == null, istruefornullandundefined, and nothing else. - Line 5,
name ?? "friend", uses"friend"only whennameisnullorundefined.
Pick a value, then compare four checks: the truthy check, === undefined, == null, and ??.
script
console.log(Boolean(name));console.log(name === undefined);console.log(name == null);console.log(name ?? "friend");Two of these checks are the ones to remember:
- Use
value == nullwhennullandundefinedshould both count as missing, and nothing else should. - Use
value ?? fallbackwhen you want a backup value only fornullorundefined.??is called the nullish coalescing operator. "Nullish" means "nullorundefined".
The Operators module has full lessons on comparisons, ??, and the related ?. operator.
Choose a fallback carefully
A fallback is a backup value. Your program uses it when the real value isn't there. Two operators can give a fallback, and they decide differently:
||uses the fallback for every falsy value.??uses the fallback only fornullandundefined.
const savedValue = "";const withOr = savedValue || "guest";const withNullish = savedValue ?? "guest"; console.log(withOr);console.log(withNullish);Line 1 stores an empty string in savedValue. In a form, an empty name might be a real choice. Line 2 uses ||. The empty string is falsy, so withOr gets "guest", and line 5 prints guest. Line 3 uses ??. The empty string is not null or undefined, so withNullish keeps it. Line 6 prints the empty string, so the console shows a blank line.
"" in both halves. || replaces every falsy value, so it gives "guest". ?? replaces only null and undefined, so it keeps "".The table tries five saved values. Read each row as: "when savedValue is this, each line gives that."
When savedValue is | savedValue || "guest" gives | savedValue ?? "guest" gives |
|---|---|---|
undefined | "guest" | "guest" |
null | "guest" | "guest" |
0 | "guest" | 0 |
"" | "guest" | "" |
false | "guest" | false |
Use || when every falsy value should mean "use the backup". For example, a search box where empty text should never count. Use ?? when 0, an empty string, or false is real data that the page should keep.
Where you'll use this
Real web pages use these checks all the time. Some examples:
- form fields the user may leave empty,
- how many of an item are in a shopping cart,
- settings that are on or off,
- search filters,
- data sent back from a server.
Each time, ask yourself one question: "Am I checking yes or no? Or am I checking whether a value is missing?"
const quantityText = ""; console.log(quantityText === "");console.log(Number(quantityText));A form field in the browser always gives you text, called a string. Line 1 stands for an empty quantity field: quantityText is "". Line 3 prints true, so the field is empty. Line 4 prints 0, because Number("") turns an empty string into zero. So check the text first. Otherwise an empty field looks the same as a quantity of zero.
function labelQuantity(quantity) { if (quantity == null) { return "missing"; } return quantity + " selected";}console.log(labelQuantity(0));Line 2 checks quantity == null. That is true only for null and undefined. So labelQuantity(0) skips the "missing" line and returns "0 selected".
const response = { displayName: "", photoUrl: null,}; const name = response.displayName ?? "Guest";const photo = response.photoUrl ?? "default-photo.png"; console.log(name === "");console.log(photo);Lines 1 to 4 stand for data sent back from a server. The displayName is an empty string. The photoUrl is null, which means there is no photo. Line 6 keeps the empty name, because "" is not null or undefined. Line 7 uses the backup photo, because photoUrl is null. Line 9 prints true, and line 10 prints default-photo.png.
const isMenuOpen = false;const buttonLabel = isMenuOpen ? "Close menu" : "Open menu"; console.log(buttonLabel);Line 1 stores one fact: the menu is closed. Line 2 uses ? :, which picks one of two values. If isMenuOpen is truthy it picks "Close menu". Otherwise it picks "Open menu". So line 4 prints Open menu. A boolean is a good fit when something has exactly two states. If it can be in three or more states, use a value with more choices, like a string.
Common mistakes
- "Empty arrays are falsy." They are truthy, like every array. Check
array.lengthinstead. - "The string
"false"is false." It is text with five characters. Only the empty string is falsy, so it is truthy. - "
nullandundefinedare the same."null == undefinedistrue, butnull === undefinedisfalse. They also mean different things. - "
typeof nullshows that null is an object." It is an old mistake in JavaScript.nullhas no properties to read. - "
if (value)is a safe check for a missing value." It also treats0,"",false, andNaNas missing.
The code below shows the first mistake. Line 3 tests the array itself. Line 7 tests how many items it has.
const cartItems = []; if (cartItems) { console.log("cart exists");} if (cartItems.length === 0) { console.log("cart is empty");}cartItems is an empty array. Line 3 asks if (cartItems). An array is always truthy, so line 4 prints cart exists. Line 7 asks whether cartItems.length is 0. It is, so line 8 prints cart is empty.
Practice exercises
5 EXERCISESPredict what each line prints, in order. Put commas between the answers.
console.log(Boolean("0"));
console.log(Boolean(""));
console.log(Boolean([]));"0" is text with one character, so true. "" is the empty string, so false. [] is an array, which is an object, so true.
The function says 0 is missing. Change the check on line 2 so that zero counts as a real quantity.
function labelQuantity(quantity) {
if (!quantity) {
return "missing";
}
return quantity + " selected";
}
console.log(labelQuantity(0));function labelQuantity(quantity) {
if (quantity == null) {
return "missing";
}
return quantity + " selected";
}
console.log(labelQuantity(0));quantity == null is true only for null or undefined. For 0 it is false, so the code skips the "missing" line and returns "0 selected".
A user clicks "Clear photo". Should the app store null, or leave the field undefined?
Use null. The user chose to clear the photo, so the app stores a value that means empty on purpose.
Which operator makes displayName(null) give "friend", but keeps "" as it is?
function displayName(name) {
return name ?? "friend";
}
console.log(displayName(null));
console.log(displayName(""));function displayName(name) {
return name ?? "friend";
}
console.log(displayName(null));
console.log(displayName(""));?? uses the fallback only for null and undefined. It keeps "", 0, and false as real values.
Which property should code check to find out whether a list is empty?
const items = [];
console.log(Boolean(items));
console.log(items.length === 0);Check items.length. An array is always truthy, so if (items) only tells you that items holds an array. It doesn't tell you whether the array has any items.
Check your understanding
7 QUESTIONSQuestion 1 of 7How many values are on JavaScript's falsy list?
Choose an answer to see the explanation.
Question 2 of 7What does
Boolean("false")print?Read the code, then predictconsole.log(Boolean("false"));Choose an answer to see the explanation.
Question 3 of 7What does
Boolean([])print?Read the code, then predictconsole.log(Boolean([]));Choose an answer to see the explanation.
Question 4 of 7Which sentence best describes
null?Choose an answer to see the explanation.
Question 5 of 7What do these two comparisons print?
Read the code, then predictconsole.log(null == undefined); console.log(null === undefined);Choose an answer to see the explanation.
Question 6 of 7What does
??do with zero?Read the code, then predictconst quantity = 0; console.log(quantity ?? 1);Choose an answer to see the explanation.
Question 7 of 7Which check counts
nullandundefinedas missing, but not0or""?Choose an answer to see the explanation.
Key takeaways
- There are exactly two booleans:
trueandfalse. - There are exactly eight falsy values:
false,0,-0,0n,"",null,undefined, andNaN. - Every object is truthy. That includes
[]and. - Use
nullto say "empty on purpose". Expectundefinedwhen no value was given. - When you mean "missing" and not just "falsy", use
== nullor??.
In one line: Truthiness is how JavaScript reads any value as yes or no. null and undefined are its two ways to say "no value here".
Up next: BigInt, a type for very large whole numbers.