New to Rust? Grab our free Rust for Beginners eBook Get it free →
Null vs undefined in JavaScript: What the difference actually means

JavaScript gives you two ways to say “there’s nothing here”: null and undefined. They look alike, behave alike in some situations, and trip up beginners and experienced developers alike. But they have different origins and mean different things. Knowing which one you’re looking at, and why, is the difference between code that breaks silently and code that fails clearly. This guide covers everything: what each value is, how to compare them, how they behave in arithmetic and JSON and how modern operators like ?? and ?. interact with both.
What is null in JavaScript?
null is a primitive value you assign on purpose to say “this variable has no value right now.” It signals intentional emptiness. JavaScript never sets a variable to null by itself, and a developer always has to write it explicitly.
A classic example is a function that searches for a record. If the record doesn’t exist, returning null is the right call because you’re making a deliberate statement: the search ran, it just found nothing.
function findUser(id, users) {
const match = users.find(user => user.id === id);
return match || null; // explicit: we searched, found nothing
}
const result = findUser(99, [{ id: 1, name: 'Alice' }]);
console.log(result); // null
You’ll also see null used to reset a reference, to tell the garbage collector that a variable no longer holds an object.
let connection = createDbConnection();
// ... use the connection
connection = null; // done with it, release the reference
What typeof null returns
One quirk every JavaScript developer hits at some point: typeof null returns "object", not "null".
console.log(typeof null); // "object"
This is a well-documented bug from JavaScript’s first release in 1995. The fix was never shipped because it would have broken too much code on the web. The takeaway: null is a primitive, but typeof lies about it. Use a strict equality check when you need to confirm something is actually null.
const x = null;
console.log(x === null); // true <-- reliable check
See our article on the typeof operator for the full picture on type checking in JavaScript.
What is undefined in JavaScript?
undefined is what JavaScript assigns automatically when a variable exists but has no value yet. Unlike null, you rarely write undefined yourself, JavaScript produces it for you in several situations.
When JavaScript produces undefined
Declared variable with no assignment:
let score;
console.log(score); // undefined
Function with no return statement:
function greet(name) {
console.log('Hello, ' + name);
// no return
}
const result = greet('Alice'); // logs 'Hello, Alice'
console.log(result); // undefined
Accessing an object property that doesn’t exist:
const user = { name: 'Alice', age: 30 };
console.log(user.email); // undefined
Accessing an array index that’s out of range:
const colors = ['red', 'blue', 'green'];
console.log(colors[10]); // undefined
What typeof undefined returns
let x;
console.log(typeof x); // "undefined"
undefined is the only value where typeof returns "undefined". No quotes around undefined here, because typeof always returns a string.
Unlike null, undefined is a global property of the window object in browsers. That means, technically, it could be overwritten in old browsers. Modern browsers prevent this at the global level, but in a non-global scope it’s still possible. Never use undefined as a variable name.
How null and undefined compare
This is where most of the confusion happens, so let’s be precise.
Loose equality (==) treats them as equal
console.log(null == undefined); // true
console.log(null == null); // true
console.log(undefined == undefined); // true
The == operator performs type coercion. When comparing null and undefined, it finds them equal regardless of their types. This is actually useful in practice: you can write if (value == null) to catch both null and undefined in a single check.
function process(input) {
if (input == null) {
// handles both null and undefined
console.log('No input provided');
return;
}
// safe to use input here
}
For more on loose vs strict comparisons, see our guide on JavaScript operators.
Strict equality (===) treats them as different
console.log(null === undefined); // false
console.log(null === null); // true
console.log(undefined === undefined); // true
=== checks both value and type. null has type "object" (that bug again) and undefined has type "undefined", so they’re not strictly equal.
A quick reference of typeof results
typeof null; // "object" <-- the legacy bug
typeof undefined; // "undefined"
null === undefined; // false
null == undefined; // true
How null and undefined behave in arithmetic
They behave differently when you do math with them.
null converts to 0 in numeric contexts:
console.log(null + 1); // 1
console.log(null * 10); // 0
console.log(+null); // 0
undefined converts to NaN (Not a Number):
console.log(undefined + 1); // NaN
console.log(undefined * 10); // NaN
console.log(+undefined); // NaN
This matters when you’re summing values from an API or a form. A field that hasn’t been filled in gives you undefined, and if you add undefined to a running total, you get NaN silently spreading through your calculations. A field explicitly cleared and set to null gives you 0 instead, which is usually safer.
const scores = [10, undefined, 5, null, 8];
const total = scores.reduce((sum, score) => sum + (score ?? 0), 0);
console.log(total); // 23
How null and undefined behave in JSON
This is one of the most practical differences between the two.
When you serialize an object to JSON with JSON.stringify(), properties with undefined values are silently dropped. Properties with null are kept.
const payload = {
name: 'Alice',
age: undefined, // will be dropped
email: null // will be kept
};
console.log(JSON.stringify(payload));
// {"name":"Alice","email":null}
age disappears entirely from the output. email stays because null is a valid JSON value and undefined is not.
This has real consequences for API work. If you send a PATCH request where null means “clear this field” and you accidentally use undefined, the field won’t appear in the body at all, and the backend may treat a missing field as “leave it unchanged” rather than “delete it.” Use null for properties that must be present even when empty.
// Safe approach for API payloads
const updatePayload = {
name: newName,
bio: userClearedBio ? null : existingBio
};
null and undefined with ?? and ?.
ES2020 introduced the nullish coalescing operator (??) and the optional chaining operator (?.). Both treat null and undefined as the trigger condition, and knowing how they work with these values prevents a class of bugs.
Nullish coalescing (??)
?? returns the right side only when the left side is null or undefined. It does not trigger on other falsy values like 0, "" or false.
const port = 0;
const safePort = port ?? 3000; // 0 <-- keeps the 0
const unsafePort = port || 3000; // 3000 <-- treats 0 as falsy
const username = null;
const display = username ?? 'Guest'; // 'Guest'
const score = undefined;
const final = score ?? 0; // 0
This distinction matters when 0 or "" are valid values you don’t want to overwrite.
Optional chaining (?.)
?. short-circuits to undefined when it hits a null or undefined in the chain, instead of throwing a TypeError.
const user = null;
// Without optional chaining
console.log(user.address.city); // TypeError: Cannot read properties of null
// With optional chaining
console.log(user?.address?.city); // undefined — no crash
Combining both operators lets you access deeply nested properties safely and supply a default:
const config = null;
const timeout = config?.settings?.timeout ?? 5000;
console.log(timeout); // 5000
How default function parameters interact with null vs undefined
This is a subtle difference that catches people out.
JavaScript default parameter values only fire when an argument is undefined. Passing null explicitly does not trigger the default.
function connect(host = 'localhost', port = 3000) {
console.log(host, port);
}
connect(undefined, undefined); // 'localhost' 3000 <-- defaults fire
connect(null, null); // null null <-- defaults don't fire
So if you pass null thinking “no value, use the default,” you’ll get null, not the default. If you want a default to fire, pass undefined or leave the argument out entirely.
// Pattern when null should use the default
function render(title = 'Untitled') {
console.log(title);
}
render(null); // null (no default)
render(undefined); // 'Untitled' (default fires)
render(); // 'Untitled' (default fires)
For more on JavaScript arrays and working with missing values in collections, that article covers similar ground around falsy checks.
Key takeaways
nullis always set by a developer on purpose.undefinedis set by JavaScript automaticallytypeof nullreturns"object"due to a legacy bug, so use=== nullfor reliable checksnull == undefinedistruebutnull === undefinedisfalsenullconverts to0in arithmetic.undefinedconverts toNaNJSON.stringifydropsundefinedproperties but keepsnullones??and?.treat bothnullandundefinedas nullish triggers- Default parameters only fire on
undefined, not onnull - Use
value == nullto check for both in a single condition
Frequently asked questions (FAQs)
What is the difference between null and undefined in JavaScript?
null is an intentional assignment meaning “no value,” set by the developer. undefined means a variable was declared but never assigned, produced automatically by JavaScript.
When should I use null vs undefined?
Use null when you want to signal that a variable is deliberately empty or cleared. Let undefined be what JavaScript assigns naturally, don’t write it yourself unless resetting a reference.
Does null equal undefined in JavaScript?
With loose equality (==), yes, null == undefined is true. With strict equality (===), no, they are different types and null === undefined is false.
Why does typeof null return object?
This is a bug from JavaScript’s first version in 1995. The internal tag for null was accidentally the same as the object tag. The fix was never shipped to avoid breaking existing web code.
What does undefined mean in a function return value?
If a function has no return statement, or has return with no value after it, JavaScript returns undefined automatically. This is different from a function that explicitly returns null.
How do null and undefined behave differently in JSON?
JSON.stringify removes properties with undefined values entirely. Properties set to null are preserved in the output. This matters a lot for API request payloads.
Can you use ?? to check for both null and undefined?
Yes. The nullish coalescing operator (??) treats both null and undefined as nullish, so value ?? 'default' returns 'default' whether value is null or undefined.
The distinction between null and undefined in JavaScript comes down to one question: was this absence of value intentional (null) or automatic (undefined)? Once you have that mental model, the quirks around typeof, ==, JSON and default parameters all make sense.


