null
Learn JavaScript null as intentional nothing, see APIs that return it, avoid property errors, and predict its math, JSON, and default behavior.
- 01Use null on purposeSet a value to
nullwhen it should be empty on purpose: no selected item, nobody logged in, no winner yet, or no result. - 02Spot null from APIsKnow which common browser and JavaScript functions return
nullwhen they find nothing. - 03Avoid null bugsCheck for
nullwith=== null,?., and??. Predict whatnulldoes in math, comparisons, JSON, and defaults.
null means "empty on purpose"
null is a special value in JavaScript. It means "empty on purpose". When a variable holds null, someone chose to leave it empty. Nobody forgot it, and it is not a mistake. It is a clear sign that says: there is no value here right now.
null is a primitive value that means "empty on purpose". A primitive value is a simple value, like a number or a piece of text. It is not an object. You put null in a place when "nothing" is the right answer. Before you use a value that might be null, check for it.
Picture a seating chart in a classroom. One seat has a card that says "reserved for nobody". The teacher chose to keep that seat empty. Another seat has no card at all. Maybe nobody has given it a student yet. The first seat is like null. The second seat is like undefined.
- In real life: A seat with a card that says: reserved for nobody
- In JavaScript: A variable set to
nullon purpose - In real life: A seat with no card yet
- In JavaScript: A variable or property that is
undefined - In real life: You read the card before you sit down
- In JavaScript: You check for
nullbefore you use the value
null in the box on purpose. On the right, the code never put anything in, so JavaScript shows undefined.The undefined lesson showed the value JavaScript gives you when something was never set. This lesson is about null, the value you choose when "nothing" is the right answer.
Setting null on purpose
STEP THROUGHUse null for a value that is allowed to be empty. Here are some everyday examples from web pages:
- No item is selected.
- Nobody is logged in.
- The game has no winner yet.
- You no longer need a big object that you were keeping.
let selectedItem = { id: "lesson-1", title: "Variables" };console.log(selectedItem.title);selectedItem = null;console.log(selectedItem);Line 1 stores a selected item: an object with an id and a title. Line 2 prints its title, Variables. Line 3 clears the selection by storing null. Line 4 prints null.
null is most useful when a value used to exist, or will exist later, but is empty on purpose right now.
script
let session = { user: "Ada" };let winner = null; function clearSelection() { selectedItem = null;} function logout() { session = null;} console.log(selectedItem?.title ?? "nothing selected");clearSelection();logout();console.log(selectedItem === null);console.log(session === null);console.log(winner ?? "no winner yet");The replay uses a longer program with the first three examples. Line 3 sets winner to null, because there is no winner yet. Line 6 clears the selected item. Line 10 empties the session after the user logs out. None of these null values is a bug. Each one tells the rest of the code: "this is empty on purpose".
let cachedReport = { rows: new Array(1000).fill("data") };console.log(cachedReport.rows.length);cachedReport = null;console.log(cachedReport);Line 1 stores a big object that holds a list of 1000 rows. Line 2 prints 1000. Line 3 sets cachedReport to null. Now this variable no longer points at the big object. Line 4 prints null.
This does not delete the object right away. JavaScript has a cleaner called the garbage collector. It frees the memory of objects that nothing points at any more. If no other variable points at the big object, the garbage collector can free it later. The Stack & heap lesson shows how this memory works.
APIs that return null
EXAMPLESAn API is a set of ready-made functions that you call, like the browser's document.getElementById(). Many APIs return null to say "I looked, and I found nothing".
The first examples use the DOM. The DOM is the browser's model of the page, and DOM functions find elements on it. These examples run on a tiny page:
- It has one button with the id
save. - No element has the id
missing. - No element has the class
none. - No element with the class
panelis around the button.
const missingById = document.getElementById("missing");const missingBySelector = document.querySelector(".none");const button = document.querySelector("#save");const missingAncestor = button.closest(".panel"); console.log(missingById);console.log(missingBySelector);console.log(missingAncestor);Line 1 looks for an element with the id missing. Line 2 looks for the first element with the class none. Line 3 finds the Save button. On line 4, closest() looks at the button and the elements around it for the class panel. None of the three searches finds anything. So lines 6, 7, and 8 each print null.
#save. The search looks for #missing and finds nothing. So it gives you null, which means "I looked, and there is no such element".console.log("abc".match(/z/));console.log(/z/.exec("abc"));console.log(localStorage.getItem("missing"));console.log(JSON.parse("null"));console.log(Object.getPrototypeOf(Object.prototype));Every line prints null:
- Line 1:
match()searches text with a pattern. The pattern is called a regular expression./z/looks for the letter z, and"abc"has no z. - Line 2:
exec()does the same search, starting from the pattern. - Line 3:
localStorageis storage in the browser that keeps text under a name. Nothing is saved under the namemissing. - Line 4: JSON text can hold
nulltoo.JSON.parse()turns it into JavaScriptnull. - Line 5: an object can borrow methods from another object, called its prototype.
Object.prototypeis the last one in that line, so its own prototype isnull. You'll see more near the end of this lesson.
const answer = prompt("Pick a name");console.log(answer);prompt() opens a small box that asks the user to type something. If the user types text and presses OK, you get that text as a string. If the user presses Cancel, you get null. You can't run this example here, because the result depends on which button you press.
console.log([1, 2, 3].find((n) => n > 5));console.log(new Map([["name", "Ada"]]).get("age"));console.log("abc".indexOf("z"));- Line 1:
find()looks through an array. It givesundefinedwhen nothing matches. - Line 2: a
Mapis a list of keys and values. Itsget()givesundefinedfor a missing key. - Line 3:
indexOf()gives-1when the text isn't found.
So before you check for null, look up what that API really returns.
Check before you use it
STEP THROUGHA safe way to work with null has three steps:
- A function returns the value it found, or
null. - You store the result in a variable.
- You check for
nullbefore you read any property.
Two short operators help with this. You'll see both below:
?.is called optional chaining. It reads a property only if the value is notnullorundefined. Otherwise it givesundefined, with no error.??is called nullish coalescing. It picks a backup value when the left side isnullorundefined.
There are also two ways to compare a value with null. == is loose equality: it may convert values before it compares them. === is strict equality: it never converts.
const selectedItem = null;const missingItem = undefined;console.log(selectedItem == null);console.log(missingItem == null);console.log(0 == null);console.log(selectedItem === null);Lines 3 and 4 use the loose check, value == null. It is true for both null and undefined. Line 5 shows that it is false for 0. Line 6 uses the strict check, value === null. Use it when only null should match.
Step through a function that returns a user object or null. Then watch the caller check for null, read safely with ?., and pick backups with ??.
script
{ id: 1, name: "Ada", photo: null }, { id: 2, name: "Linus", photo: "linus.png" },]; function findUser(id) { const match = users.find((user) => user.id === id); return match ?? null;} function describeUser(id) { const user = findUser(id); const name = user?.name ?? "Guest"; if (user === null) { return name + ": no account"; } const photo = user.photo ?? "default.png"; return name + ": " + photo;} console.log(describeUser(3));Pick "Missing user 3" first. Line 7 searches the list and gets undefined. Line 8 turns that undefined into null, so the meaning is clear. Line 14 checks for exactly null. So line 15 returns early, before any property of null is read. Then pick Ada. Ada is a real user, but her photo is null on purpose, because she has no photo.
typeof null says "object"
typeof is an operator that tells you the type of a value, as text. typeof null gives "object". This is a mistake from the first version of JavaScript, in 1995. It was never fixed, because the fix would break old websites. null is still not an object, and you can't use it like one. The full story is in Null inside the engine.
const value = null;console.log(typeof value);console.log(value === null);console.log(Object.prototype.toString.call(value));Line 2 prints object, the old mistake. Line 3 is the check you should write: value === null. It prints true. Line 4 uses an older helper, Object.prototype.toString.call(), that names the kind of a value. It correctly prints [object Null].
Reading a property of null fails
When you read a missing property from a real object, you get undefined. Reading a property from null is different. There is no object to read from, so JavaScript stops and throws an error. Chrome and Node run JavaScript with the V8 engine. V8 shows this message for the next example: TypeError: Cannot read properties of null (reading 'name').
const profile = null;console.log(profile.name);null, so there is no object and no name to read. A plain read throws an error. With ?. the read stops safely, and ?? picks the backup text.const profile = null;if (profile === null) { console.log("No profile");}console.log(profile?.name ?? "No name");Line 2 checks for null first, so line 3 prints No profile. This is the clearest way for a beginner. Line 5 does the same job in one line:
profile?.namestops atnulland givesundefined, not an error.?? "No name"then picks the backup text. So line 5 printsNo name.
null in math and comparisons
When JavaScript needs a number, it turns null into 0. But == has its own rule for null. So null == 0 is false, even though null becomes 0 in math.
console.log(null + 1);console.log(undefined + 1);Line 1 turns null into 0, then adds 1. It prints 1. Line 2 turns undefined into NaN. NaN means "not a number": a result that is not a usable number. So line 2 prints NaN.
console.log(Number(null));console.log(Number(undefined));console.log(null + 1);console.log(null * 3);console.log(null == 0);console.log(null >= 0);console.log(null > 0);console.log(null == undefined);console.log(null === undefined);console.log(null < 1);Read this code in three parts:
- Lines 1 to 4 do math.
nullbecomes0, andundefinedbecomesNaN. - Lines 6, 7, and 10 use
>=,>, and<. These turnnullinto0first. Sonull >= 0istrue,null > 0isfalse, andnull < 1istrue. - Lines 5, 8, and 9 check if two values are equal.
==does not turnnullinto a number. It treatsnullas equal only tonullandundefined. So line 5 printsfalse, and line 8 printstrue. Line 9 uses===, which keeps them apart, so it printsfalse.
>= turn null into 0 first. == does not. It treats null as equal only to null and undefined.Try each operation
PLAYGROUNDPick a value and an operation. The code shows the exact line that runs. The result comes from real JavaScript, and the note under it names the rule that was used.
const value = null;console.log(value + 1);null is empty on purpose. value + 1 gives 1. `+` turns `null` into 0, but `undefined` into NaN, which means "not a number". With text, `+` joins the text instead.
null is empty on purpose. value + 1 gives 1. + turns null into 0, but undefined into NaN, which means "not a number". With text, + joins the text instead.
null in JSON and defaults
JSON is a text format for sending data, for example from a server to a web page. JSON has its own null, so it keeps null values.
A default is a backup value that you write in two places:
- In a function's parameters, like
name = "friend". This is a default parameter. - In destructuring, which copies properties of an object into variables. Line 4 below does this, with the default
"avatar.png".
Defaults only replace undefined. They do not replace null. To replace null, use ?? or ||.
function greet(name = "friend") { return `Hi, ${name}`;}const { photo = "avatar.png" } = { photo: null }; console.log(JSON.stringify({ photo: null }));console.log(greet(null));console.log(greet(undefined));console.log(photo);console.log(null ?? "fallback");console.log(null || "fallback");- Line 6 prints
{"photo":null}. JSON keeps thenull. - Line 7 prints
Hi, null. The default"friend"is not used. - Line 8 prints
Hi, friend. The default replacesundefined. - Line 9 prints
null. The default on line 4,"avatar.png", is not used either. - Lines 10 and 11 both print
fallback.??replaces onlynullandundefined.||also replaces0,"", andfalse. Try both in the playground above.
The prototype chain ends at null
An object can borrow properties from another object, called its prototype. That prototype can have its own prototype, and so on. This line of objects is the prototype chain. For a normal object, the chain reaches Object.prototype. The prototype of Object.prototype is null, so the chain ends there. You can also make an object with no prototype at all, with Object.create(null).
const chainEnd = Object.getPrototypeOf(Object.prototype);console.log(chainEnd); const dictionary = Object.create(null);dictionary.answer = 42;console.log("toString" in dictionary);console.log(dictionary.answer);Line 1 asks for the prototype of Object.prototype, and line 2 prints null. Line 4 makes dictionary, an object with no prototype. Line 5 gives it its own property, answer.
On line 6, "toString" in dictionary asks: does this object have, or borrow, a property called toString? Normal objects borrow it. This one borrows nothing, so line 6 prints false. Line 7 prints 42, because its own properties still work.
Does JavaScript give you null, undefined, or something else?
SORTERDifferent APIs say "not found" in different ways. Sort each card by the value that API gives when it finds nothing.
document.getElementById("missing")document.querySelector(".none")button.closest(".panel") when nothing around it matches"abc".match(/z/)/z/.exec("abc")localStorage.getItem("missing")prompt() when the user cancelsJSON.parse("null")Object.getPrototypeOf(Object.prototype)[].find(...) with no matchnew Map().get('missing')object.missingA function that reaches the end with no return"abc".indexOf("z")document.querySelectorAll(".none")
Sort each API by the value it gives when it finds nothing.
Where null shows up in real code
Use null when "empty" is a normal state in your app. For example:
- A search result is
nullbefore the user picks anything. - A session becomes
nullafter the user logs out. - A server sends
{ "photo": null }to say the user has no photo. - A page search returns
nullwhen no element matches.
The habit is always the same. Make it clear that the value can be empty. Then check it before you read its properties. If both null and undefined should get a backup value, use ??. If only null should match, use value === null.
const apiResponse = { displayName: "Asha", photo: null };console.log(apiResponse.photo);console.log(apiResponse.photo === null);Line 1 is the data a server sent back. It has photo: null to say Asha has no photo. Line 2 prints null. Line 3 checks for exactly null and prints true.
Common misconceptions
- “
nullis an object.” It isn't.typeof nullsays"object"because of an old mistake.nullis a primitive value. - “Defaults replace
null.” They don't. Default parameters and destructuring defaults only replaceundefined. - “
null == 0is true, becauseNumber(null)is 0.” It's false.==has its own rule:nullis equal only tonullandundefined. - “Reading a missing property and reading from
nullare the same.” They aren't. A missing property givesundefined. Reading any property fromnullthrows an error. - “Every API returns
nullwhen it finds nothing.” Some returnundefined,-1, or an empty list.
The table below compares four values that can all look "empty". Each row runs one piece of code on all four. Read across a row to see how the four values differ.
| What you run | null | undefined | 0 | "" |
|---|---|---|---|---|
typeof value | "object" | "undefined" | "number" | "string" |
Boolean(value) | false | false | false | false |
Number(value) | 0 | NaN | 0 | 0 |
value == null | true | true | false | false |
JSON.stringify({ v: value }) | {"v":null} | {} | {"v":0} | {"v":""} |
function f(x = "d") { return x; } | f(null) is null | f(undefined) is "d" | f(0) is 0 | f("") is "" |
Practice exercises
6 EXERCISESPredict the three lines this code prints, in order.
console.log(Number(null));
console.log(null + 1);
console.log(null == undefined);The three lines print 0, 1, and true.
Replace profile.name with a safe version that prints No name.
const profile = null;
console.log(profile.name);const profile = null;
console.log(profile?.name ?? "No name");profile?.name stops at null instead of throwing an error. Then ?? "No name" picks the backup text.
This code searches "abc" for the letter z. What does it print?
console.log("abc".match(/z/));"abc".match(/z/) returns null, because there is no z in "abc".
Predict both lines this code prints.
function greet(name = "friend") {
return "Hi, " + name;
}
console.log(greet(null));
console.log(greet(undefined));greet(null) prints Hi, null. greet(undefined) prints Hi, friend.
The user clicks Clear selection. Which value should the code store?
let selectedItem = { title: "JavaScript basics" };
selectedItem = null;
console.log(selectedItem);Set the variable to null when the user clears the selection on purpose.
What does the "toString" in dictionary line print?
const dictionary = Object.create(null);
dictionary.answer = 42;
console.log("toString" in dictionary);
console.log(dictionary.answer);The first line prints false. The dictionary doesn't borrow toString.
Check your understanding
8 QUESTIONSQuestion 1 of 8What does
nullmean?Choose an answer to see the explanation.
Question 2 of 8What does this print?
Read the code, then predictconsole.log(typeof null);Choose an answer to see the explanation.
Question 3 of 8What error does this code throw in Chrome and Node?
Read the code, then predictconst profile = null; console.log(profile.name);Choose an answer to see the explanation.
Question 4 of 8What do these two lines print?
Read the code, then predictconsole.log(null + 1); console.log(null >= 0);Choose an answer to see the explanation.
Question 5 of 8What do these equality checks print?
Read the code, then predictconsole.log(null == 0); console.log(null == undefined); console.log(null === undefined);Choose an answer to see the explanation.
Question 6 of 8What JSON text does this print?
Read the code, then predictconsole.log(JSON.stringify({ photo: null, nickname: undefined }));Choose an answer to see the explanation.
Question 7 of 8What does this code with a default parameter print?
Read the code, then predictfunction greet(name = "friend") { return "Hi, " + name; } console.log(greet(null)); console.log(greet(undefined));Choose an answer to see the explanation.
Question 8 of 8What does this code with
?.and??print?Read the code, then predictconst user = null; console.log(user?.name ?? "Guest");Choose an answer to see the explanation.
Key takeaways
nullis a primitive value that means "empty on purpose".- Your code, or an API, puts
nullin a place on purpose. - Check for exactly
nullwithvalue === null. typeof nullgives"object"because of an old mistake. Don't treatnulllike an object.- Reading a property of
nullthrows an error. Check first, or use?.. - In math,
nullbecomes0. Butnull == 0is stillfalse. - JSON keeps
null. Default parameters and destructuring defaults don't replace it.
Final definition: null is the JavaScript value for something that is empty on purpose.
Up next: Booleans, null & undefined compares all three side by side. To see how the engine stores null, visit Null inside the engine.