Undefined: You’re Using It Wrong
One of the very first questions about JavaScript that arises in the heads of beginner developers is “What’s the difference between null
and undefined
?” This lack of understanding takes place because both of them indicate some kind of emptiness, but each in its own different way.
What are those?
null
The difference is about certainty. null
basically says “there’s nothing here, move along.” And this is for real, you can be certain about that. null
can be found in places where the value is optional or might not exist. E.g. when finding a word in an input string, it might or might not actually be found:
const input = "Tony Stark";input.match(/Stark/g);
// [ "Stark" ]input.match(/Iron Man/g);
// null
The second expression returns null
because the input string does not include "Iron Man"
as part of self.
When dealing with JSON, it has no concept of “undefined”, therefore empty values in JSONs will too be indicated as null
:
{
"organization": "S.H.I.E.L.D.",
"head": "Nick Fury, director",
"members": null
}
In fact,JSON.stringify
will even omit properties with undefined
value:
const value = { redSkull: undefined };JSON.stringify(value);
// "{}"
undefined
undefined
is slightly more difficult to understand. In most cases, it says that value of the accessed entity is “hazy” and/or has not yet been well defined. JavaScript tells that “nothing is certain about this value.” For example, if one tried to access a non-existent property of an object:
const person = { name: "Natasha Romanoff" };person.age;
// undefined
… one will predictably get undefined
as a response, because… well, the value of this property is not defined, it does not exist. Same thing for uninitialized variables:
let theOtherGuy;theOtherGuy;
// undefined
For undeclared variables though, the situation is somewhat more complicated. When accessing undeclared variables in strict mode, you’ll get a ReferenceError
thrown, and this will prevent further execution of logic. In “sloppy” mode however you’ll get an undefined
, as if like everything is just fine. That’s why I highly encourage you to always hack in strict mode, because it eliminates a lot of possible errors and misunderstandings right away.
Keep in mind, that neither null, nor undefined has any properties. Accessing them is a ReferenceError still.
How can I use it wrong?
Remember what I’ve said earlier about certainty? Now, what if I used undefined
explicitly?
const person = { name: "Natasha Romanoff", age: undefined };// …
// (a lot of code)
// …person.age;
// undefined
When accessing person.age
, the value is undefined
, but what does it mean exactly? What it should mean is that the property age
does not exist in the person
object. But it actually does exist, therefore something else has to be going on here.
The original intention was to indicate that there’s no information about the person’s age at the moment. But the actual response says that the age is “hazy” and is not yet well defined. This behavior might be interesting from a philosophical or sociological perspective, but in the code this doesn’t make sense and usually means that somebody screwed up.
Another problem is that until you see the code, you never know whether this undefined
is explicit or not. That is, whether it was written explicitly by developer as a placeholder for future use, or yielded by the JavaScript interpreter as a result of some invalid expression. Needless to say, those situations require different kinds of treatment.
How can I be sure that I use it properly?
First of all, if you decide to never use undefined
explicitly, you will make your life and life of your colleagues much easier. Simply put, if you see undefined
where should be some value, you can be sure that there is some sneaky error, hiding in the code, that will sooner or later break the app in an unexpected way (if not already).
Additionally, to protect the team from encountering strange values all over the place, you can use some kind of validation strategy, which will guarantee that the value, you’re dealing with now, is exactly what you’re expecting it to be:
function getName(person) {
if (person == null)
throw new Error("The argument has to be defined"); return person.name;
}getName({ hero: "Hulk", name: "Bruce Banner" });
// "Bruce Banner"getName();
// Error: The argument has to be defined
Valuer is a best fit for this kind of task. It is a flexible tool, that will allow you to create concise yet informative descriptions for expected values, spot errors early and provide a lot of useful details along the way. Plus, it integrates seamlessly into the existing code:
const { valuer } = require("@valuer/main");const person = { name: "Thor Odinson" };valuer(person.age, "age").as("defined", "number");
// Error: Validation failed: age is undefinedperson.age = 1500; // hotfixconst age = valuer(person.age, "age").as("defined", "number");
// (no errors)console.log(age);
// 1500
Neat, isn’t it?
This little article is my first of a kind. Did it help you to better understand the concepts of null and undefined? If you’re sure that there’s more in that, please, share the thought in the comments section below.
Lucky hacking!