Two kinds of nothing
`undefined` means nobody supplied a value; `null` means somebody supplied its absence. Mixing them is a design decision you make once.
Most languages have one word for nothing. JavaScript has two, and having two is not the mistake it is usually said to be. They mean genuinely different things, and the trouble starts when a program uses them interchangeably.
Here is where the first one comes from without anybody writing it.
Add = 5 to the end of the first line and run it again.
Declaring a name without giving it a value leaves it holding undefined. Nobody typed that word. The language put it there to mean "this exists and has not been given anything".
Call greet a third time with two arguments instead of one and see whether it complains.
The second call left the argument out, and JavaScript did not object. A parameter with no argument behind it holds undefined, which is why the output reads "hello, undefined" rather than stopping with an error.
Add return 7; as the last line inside the function and run it again.
A function that never says what to give back gives back undefined. Three different situations, one value, and a pattern behind all of them.
Where each one comes from
undefined arrives on its own, in five situations.
- A name declared with nothing assigned to it.
- A parameter the caller did not supply.
- A property read from an object that does not have it.
- A function that finishes without returning anything.
- A slot in an array that was never filled.
null never arrives that way. The engine does not fill a hole with null: every gap it fills on its own it fills with undefined. null has to be put there by something that went and looked.
Usually that something is a person, writing null into the code or into the data. A handful of standard operations produce it too, and they mean the same thing by it: looked, found nothing, saying so.
Change the "z" on the first line to "b" and watch only that line move. A search that finds something answers with what it found.
Three reported absences. A search through text that matches nothing answers null. A chain of objects that has run out answers null, which the section on prototypes returns to. Reading the text null out of a file gives the value null, because that is what the text said.
None of those is the language quietly filling in a blank. Each is an operation reporting the result of a search, which is the same thing a person means when they write null by hand.
They are not equal, and they are
Replace undefined in the first two lines with 0, then with false, and note that both answers become false.
Two comparison operators, two answers. === is strict equality: same type and same value, with no conversion of any kind. Since null and undefined are different types, it says false.
== is loose equality, which converts before comparing. Its rules have a whole section of this course later on. One of them is written in specifically for this case: null and undefined are loosely equal to each other and to nothing else at all.
That single rule is genuinely useful. value == null is the shortest correct way to ask "is this either kind of nothing?", and it is the one place where experienced JavaScript programmers reach for == on purpose.
Where the difference bites
A default parameter is a value a function uses when an argument is missing, written with = in the parameter list. It checks for one specific thing, and it is worth knowing which.
Change the default from "medium" to "small" and check that only two of the three lines move.
Passing undefined triggered the default. Passing null did not, and the function returned null. A default parameter tests for undefined alone, because null is a value, and sending a value is something the caller chose to do.
This is the single most common way the two get confused in real code. A function reads a field from some data, the field is missing, and null from a database arrives where undefined was expected. The default never fires and the rest of the function works with null.
Swap the two values so a is undefined and b is null, and see which key survives.
JSON is the format almost all data travels in, and it has null and no undefined whatsoever. A property holding undefined is dropped entirely on the way out. If you write data to a file or send it over a network, undefined does not survive the trip and null does.
What to do in your own code
- Pick one to mean "no value" and use it everywhere in the code you own.
- Never return both from the same function. Every caller then has to test twice, and one of them will forget.
- For an absence you store, send or write down, prefer
null, because it survives JSON andundefineddoes not. - Leave
undefinedto the language. It is what you get when something was not supplied, which is information rather than a value. - When reading somebody else's data, treat both the same and normalise once, at the edge, so the inside of your program only ever sees one of them.
A function looks up a customer by id and there is no customer with that id. Should it return null or undefined?
null. The function looked, and the answer is a definite absence, which is exactly what null means. Returning undefined would be indistinguishable from the function having a bug and forgetting to return at all. It also survives being written to JSON, so the same answer can be sent on unchanged.