Every JavaScript beginner meets the same confusing moment: your code prints undefined in one place and null in another, and they look like they mean the same thing. They do not. Understanding JavaScript null vs undefined, explained with examples, is one of those small investments that pays off every single day you write JavaScript, because these two values show up in function returns, object properties, API responses, and bug reports alike.
The short version: undefined means “this variable exists but nothing has been put in it yet,” while null means “someone deliberately put an empty value here.” That one-sentence distinction explains almost everything. The rest of this guide unpacks it with real code you can run, the comparison quirks that trip people up, and practical rules for which one to use in your own code.
In This Guide
- What undefined Means in JavaScript
- What null Means in JavaScript
- Null vs Undefined: The Key Differences Side by Side
- How Each One Shows Up in Real Code
- Comparison Quirks: ==, ===, and typeof
- Best Practices: When to Use Which
- Modern Tools: Optional Chaining and Nullish Coalescing
- Frequently Asked Questions
- Key Takeaways
- Conclusion
What undefined Means in JavaScript
is a primitive value that JavaScript assigns automatically when something has been declared but has no value yet. You rarely write
undefinedundefined yourself — the language produces it for you in several everyday situations:
// 1. A declared variable with no assignment
let username;
console.log(username); // undefined
// 2. A function parameter that was not passed an argument
function greet(name) {
console.log("Hello, " + name);
}
greet(); // Hello, undefined
// 3. A function with no return statement returns undefined
function doNothing() {}
console.log(doNothing()); // undefined
// 4. Accessing an object property that does not exist
const user = { name: "Priya" };
console.log(user.age); // undefined
// 5. An array slot that was never filled
const items = [10, 20];
console.log(items[5]); // undefined
Think of undefined as JavaScript’s way of saying “I looked, and there is nothing here yet.” It is the default, accidental empty — a placeholder the engine inserts when no value was ever provided.
What null Means in JavaScript
null is also a primitive value, but unlike undefined it never appears by accident. It only exists because a programmer deliberately wrote it. It means “this variable intentionally holds no value right now.”
// A search that found nothing returns null on purpose
let selectedUser = null;
// Later, when the user picks someone:
selectedUser = { name: "Arjun", id: 42 };
// Resetting back to "deliberately empty":
selectedUser = null;
This intentional emptiness is the whole point. When you see null in code, someone made a decision: this thing exists, it could hold a value, and right now it explicitly holds none. Common places you will meet it:
- DOM methods:
document.getElementById("missing-id")returnsnullwhen no element matches — the browser deliberately telling you “nothing found.” - JSON data from APIs:
{"middleName": null}means the field exists but has no value, which is different from the field being absent entirely. - Clearing references: setting an object to
nullsignals that it is done being used.
The MDN documentation on null and the MDN documentation on undefined are the authoritative references for the exact semantics.
Null vs Undefined: The Key Differences Side by Side
| Aspect | undefined |
null |
|---|---|---|
| Meaning | Declared but never assigned a value | Deliberately assigned as “no value” |
| Who creates it | JavaScript itself, automatically | The programmer, intentionally |
typeof result |
"undefined" |
"object" (a famous historical quirk) |
| JSON representation | Property is dropped: JSON.stringify({a: undefined}) gives "{}" |
Property is kept: JSON.stringify({a: null}) gives '{"a":null}' |
| In arithmetic | Becomes NaN: undefined + 1 is NaN |
Becomes 0: null + 1 is 1 |
| Default parameters | Triggers the default: function f(x = 5) {}, f(undefined) uses 5 |
Does not trigger the default: f(null) passes null |
Two rows in that table deserve emphasis because they cause real bugs. First, typeof null === "object" is a bug from the very first JavaScript implementation that was never fixed for backward-compatibility reasons — so never use typeof to detect null; compare with === null directly. Second, the JSON behavior means an API sending {"a": undefined} effectively sends {}, while {"a": null} explicitly sends an empty field — a meaningful difference when a backend distinguishes “field missing” from “field empty.”
How Each One Shows Up in Real Code
Let us trace both values through a realistic snippet — the kind of form-handling code beginners write when learning addEventListener:
const form = document.getElementById("signup-form");
const nicknameInput = document.getElementById("nickname");
form.addEventListener("submit", (event) => {
event.preventDefault();
// undefined: the input element exists, but the user typed nothing
// and we never set a fallback — nickname is an empty string here,
// but imagine we read a missing data attribute instead:
const referral = nicknameInput.dataset.referral; // undefined (attribute absent)
// null: we deliberately model "no referrer chosen yet"
let referrer = null;
if (referral) {
referrer = referral;
}
console.log(typeof referral); // "undefined"
console.log(referrer === null); // true
});
Notice the pattern: undefined arrived uninvited (the data attribute simply was not there), while null was a conscious modeling choice. When you later serialize this to send to a server, undefined fields vanish from the JSON while null fields arrive explicitly empty — which is exactly what most APIs expect.
Comparison Quirks: ==, ===, and typeof
This is where most beginner bugs live. JavaScript has two equality operators, and they treat null and undefined very differently:
console.log(null == undefined); // true (loose equality: both are "empty-ish")
console.log(null === undefined); // false (strict equality: different types)
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (the historical quirk!)
The loose equality == considers null and undefined equal to each other (and to nothing else — null == 0 is false, undefined == false is false). This is actually useful: value == null is a concise way to check for either null or undefined in one test. Many style guides forbid == generally but explicitly allow this one case.
Strict equality === distinguishes them, which is what you want when the difference matters — for example, when a function treats “argument not passed” (undefined, use the default) differently from “argument explicitly cleared” (null, keep it empty):
function setAvatar(url) {
if (url === undefined) {
url = "default-avatar.png"; // not passed: use the default
}
// if url === null, the caller explicitly wants NO avatar — respect it
renderAvatar(url);
}
setAvatar(); // uses default-avatar.png
setAvatar(null); // renders with no avatar, as requested
setAvatar("me.png"); // renders me.png
The rule of thumb: default to === everywhere, and reach for == null only as a deliberate shorthand for “missing in either sense.”
Best Practices: When to Use Which
Now the practical question: in your code, which one should you write? Follow these conventions and your code will be predictable to every JavaScript developer who reads it:
- Never assign
undefinedyourself. If you need an intentional empty value, usenull. Writinglet x = undefineddestroys the useful signal that “undefined means the language put this here, not me.” - Use
nullfor intentional emptiness. Initializing a variable that will hold an object later, representing “no result” from a search, clearing a reference — these are allnulljobs. - Let
undefinedmean “not yet.” Unset options, missing function arguments, absent object properties — leave these asundefinedand check for them with=== undefinedor the== nullshorthand. - Be consistent within a codebase. The worst outcome is a project where half the functions return
nullfor “not found” and the other half returnundefined. Pick one convention for your APIs and document it. - Check existence before accessing properties. Both values throw
TypeError: Cannot read properties of null (reading 'x')(or of undefined) when you access a property on them. Guard with an explicit check or use optional chaining from the next section.
Modern Tools: Optional Chaining and Nullish Coalescing
Modern JavaScript gives you two operators designed precisely for the null/undefined problem. They treat null and undefined as one category — “missing” — which is exactly right for defensive code.
Optional chaining (?.)
Instead of crashing on a missing nested property, ?. short-circuits to undefined:
const response = { data: null };
// Old way: crashes with TypeError
// console.log(response.data.user.name);
// Safe way: evaluates to undefined, no crash
console.log(response.data?.user?.name); // undefined
// Also works for function calls and array access
console.log(user.getName?.()); // undefined if getName does not exist
console.log(items?.[0]); // undefined if items is null/undefined
Nullish coalescing (??)
?? provides a fallback only when the left side is null or undefined — unlike ||, which also triggers on 0, "", and false:
const timeout = config.timeout ?? 3000;
console.log(timeout); // 3000 if config.timeout is null or undefined
// but 0 if config.timeout is 0 (|| would wrongly give 3000)
This distinction matters in real interfaces: a volume slider set to 0 is a deliberate choice, not a missing value. Pairing ?. with ?? — for example const name = user?.profile?.name ?? "Guest" — handles almost every null/undefined situation in one readable line. If you are building interactive pages, our dark mode toggle guide shows these operators handling real user preferences in practice.
Frequently Asked Questions
Is null an object in JavaScript?
No, null is a primitive value, but typeof null returns "object" due to a bug in the original 1995 implementation that could never be fixed without breaking the web. Always test for null with value === null, never with typeof.
Why does my function return undefined when I forget return?
Every JavaScript function returns undefined by default if execution reaches the end without hitting a return statement. This is the language’s automatic-empty behavior, not an error — though it usually means you forgot to return the value you computed.
Should I check with == null or === undefined?
Use value == null when you want to catch both null and undefined in one check (the standard “is it missing?” test). Use value === undefined or value === null when the distinction between “never set” and “deliberately empty” matters to your logic.
What is the difference between null and undefined in JSON?
JSON.stringify drops properties whose value is undefined but keeps properties whose value is null. So {"a": null} transmits an explicit empty field, while {"a": undefined} transmits {}. APIs often treat these differently, so be deliberate about which one you send.
Can I use null and undefined interchangeably?
Technically your code will often work, but you should not. Keeping undefined for “not yet assigned” and null for “intentionally empty” gives every reader — including future you — a reliable signal about what the code means.
What does “Cannot read properties of undefined” mean?
You tried to access a property (like user.name) on something that is undefined or null. The fix is to find out why the variable is empty — trace where it was supposed to get its value — and guard the access with a check or optional chaining (?.) in the meantime.
Key Takeaways
undefinedmeans “declared but never given a value” and is produced automatically by JavaScript;nullmeans “deliberately empty” and is always assigned by a programmer.null == undefinedistruebutnull === undefinedisfalse— use strict equality by default and the== nullshorthand only deliberately.typeof nullreturns"object"due to a historical bug; test for null with=== null.- Never assign
undefinedyourself; usenullfor intentional emptiness and keep the two meanings distinct. - Optional chaining (
?.) and nullish coalescing (??) safely handle both values — prefer??over||when0or""are valid values.
Conclusion
JavaScript null vs undefined stops being confusing the moment you internalize the core distinction: undefined is JavaScript’s automatic “nothing here yet,” and null is your deliberate “nothing here on purpose.” Write null when you mean empty, never assign undefined by hand, compare with ===, and lean on ?. and ?? for safe access. With these habits, the two empties become a precise communication tool instead of a source of bugs.