DEV Community

Anusree V A
Anusree V A

Posted on

5 Simple ways to check for undefined or null values

Ever had trouble with undefined or null values?

It is a common mistake to use a value in your code without first checking whether it's null or undefined, for example, when trying to access an object's property or calling a function.

Many of you might be familiar with the following error :

An error caused due to undefined variable

Sometimes, the program won't throw any errors but there might be unexpected behavior. For example:

const data = [
  {
    name: "Voltage 1",
    reading: 0,
    unit: "V",
  },
  {
    name: "Current 1",
    reading: 30,
    unit: "A",
  },
  {
    name: "Voltage 2",
    reading: 25,
    unit: null,
  },
  {
    name: "Current 2",
    reading: 0,
    unit: "A",
  },
  {
    name: "Voltage 2",
    unit: "V",
  },
  {
    name: "Current 2",
    reading: null,
    unit: "A",
  },
];

let newData = {};

for (const item of data) {
  newData[item.name] = `${item.reading} ${item.unit}`;
}

/* Prints : 
{
  'Voltage 1': '0 V',
  'Current 1': '30 A',
  'Voltage 2': 'undefined V',
  'Current 2': 'null A'
}
*/

Enter fullscreen mode Exit fullscreen mode

Not exactly want we wanted, is it?

It is very important to check for such values and in this post I am going to explain 5 easy ways to achieve the same.

But before that, let me first explain what falsy and nullish values are because I have seen people do a check for falsy values when what they actually need to do is a check for nullish values (in fact, I used to do the same mistake a lot in the beginningπŸ˜…).

But many of you might already be familiar with all of these, so feel free to skip ahead.

So, what are falsy and nullish values and what is the difference between them?

According to the MDN Web Docs, a falsy value is any value that is considered false when encountered in a Boolean context.

In JavaScript, the following values are considered falsy:

A complete list of falsy values in JavaScript
Image Credits : Table from MDN Docs

This means that

if (0) {
  // not reachable
}
Enter fullscreen mode Exit fullscreen mode

is equivalent to

if (false) {
  // not reachable
}
Enter fullscreen mode Exit fullscreen mode

What are nullish values then?

A value which is either null or undefined is called a nullish value.

This means that out of the 9 falsy values listed above only two (null and undefined) are considered nullish.

Remember,

All nullish values are always falsy but not the other way around

Now, since we have cleared that let us move onto our main topic, the different ways we can check for falsy and nullish values...

1. Using a simple if...else statement

Checking for falsy values using if...else statement is extremely simple. All you have to do is :

if (value) {
   // control will reach here only if value is not falsy
} else {
  //  control will reach here if value is falsy
}
Enter fullscreen mode Exit fullscreen mode

Here value is some variable.

The check for nullish values is similar, here we have to use the Equality (==) operator since if one of the operands is null or undefined, for it to return true, the other must also be null or undefined.

if (value == null) {
   // control will reach here only if value is nullish
} else {
  //  control will reach here if value is not nullish
}
Enter fullscreen mode Exit fullscreen mode

2. Using the conditional ternary operator

The logic used here is the same as that of if...else statement. In fact, the conditional ternary operator is frequently used as an alternative to an if...else statement especially when we are dealing with assignments.

Consider the code snippet given below :

const data = [
  {
    name: "Voltage 1",
    reading: 0,
  },
  {
    name: "Current 1",
    reading: 30,
  },
  {
    name: "Voltage 2",
    reading: 25,
  },
  {
    name: "Current 2",
    reading: 0,
  },
  {
    name: "Voltage 2",
  },
  {
    name: "Current 2",
    reading: null,
  },
];

let newData = {};

for (const item of data) {
  newData[item.name] = item.reading;
}

console.log(newData);

/* Prints : 
{
  'Voltage 1': '0',        
  'Current 1': '30',       
  'Voltage 2': 'undefined',
  'Current 2': 'null'      
}
*/

Enter fullscreen mode Exit fullscreen mode

Now let's say I want it to print "No Data" when there is no actual reading instead of showing undefined or null.

Lets try adding a check for falsy values first.

let newData = {};

for (const item of data) {
  newData[item.name] = item.reading ? item.reading: "No Data";
}

console.log(newData);

/* Prints : 
{
  'Voltage 1': 'No Data',
  'Current 1': '30',
  'Voltage 2': 'No Data',
  'Current 2': 'No Data'
}
*/
Enter fullscreen mode Exit fullscreen mode

Here, value of Voltage 2 and Current 2 are as we expected, but for Voltage 1 it wrongly says that there is no data where in fact, we have a reading of 0. This is because 0 is a falsy value.
Here what was required was a check for nullish values, instead we were using a check for falsy values.
So let's correct our code and try again, shall we?

let newData = {};

for (const item of data) {
  newData[item.name] =
    item.reading !== undefined && item.reading !== null
      ? item.reading
      : "No Data";
}

console.log(newData);

/* Prints : 
{
  'Voltage 1': '0',
  'Current 1': '30',
  'Voltage 2': 'No Data',
  'Current 2': 'No Data'
}
*/
Enter fullscreen mode Exit fullscreen mode

Finally, we have got it right!

Here, I have used the Strict equality (===) operator, but feel free to use the normal Equality operator like in the previous example for if...else. Both will give the same output.

Now is there a better way to do this? With less code?
Actually there is!

3. Using the nullish coalescing operator (??)

In my opinion, using the nullish coalescing operator (??) is a wonderful way to check for nullish values during assignment.

Let's see it in action first :

let newData = {};

for (const item of data) {
  newData[item.name] = item.reading ?? "No Data";
}

console.log(newData);

/* Prints : 
{
  'Voltage 1': '0',
  'Current 1': '30',
  'Voltage 2': 'No Data',
  'Current 2': 'No Data'
}
*/
Enter fullscreen mode Exit fullscreen mode

That's it. Simple.

Now let me expalin how this happens.

The syntax of nullish coalescing operator is like this:

expr1 ?? expr2
Enter fullscreen mode Exit fullscreen mode

It first checks if expr1 is null or undefined, if it is, then it returns expr2 else returns expr1.

Quite neat, isn't it?

4. Using the optional chaining operator (?.)

Now what if our data had a different format.

Take the example below :

const data = [
  {
    name: "Voltage 1",
    morningReading: {
      reading: 10,
      timestamp: "",
    },
    eveningReading: {
      reading: 25,
      timestamp: "",
    },
  },
  {
    name: "Voltage 2",
    morningReading: {
      reading: null,
      timestamp: "",
    },
  },
  {
    name: "Voltage 3",
    morningReading: {
      reading: 0,
      timestamp: "",
    },
    eveningReading: {
      timestamp: "",
    },
  },
];

for (const item of data) {
  newData[`${item.name} morningReading`] =
    item.morningReading.reading ?? "No Data";
  newData[`${item.name} eveningReading`] =
    item.eveningReading.reading ?? "No Data";
}
console.log(newData);
Enter fullscreen mode Exit fullscreen mode

What do you think will happen?

Since in the second object "Voltage 2" there is no property named "eveningReading", when we try to access item.eveningReading.reading the program will throw an error.

One way to ensure such errors don't come is to use an if condition prior to accessing chained properties.

for (const item of data) {
  if (item.eveningReading) {
    console.log(item.eveningReading.reading);
  }
}
/* Prints
25
undefined
*/
Enter fullscreen mode Exit fullscreen mode

Here, item.eveningReading.reading will only be evaluated if item.eveningReading is not nullish, hence there won't be any errors.
You can also use conditional ternary operator to achieve a similar result.

But we can simplify it further using the optional chaining operator (?.).

Let's see how it's done :

for (const item of data) {
  console.log(item.eveningReading?.reading);
}
/* Prints
25
undefined
undefined
*/
Enter fullscreen mode Exit fullscreen mode

Here, first the program checks if item.eveningReading is nullish, if it is, then the expression short-circuits with a return value of undefined else it will evaluate the whole expression item.eveningReading?.reading.

5. Combining the nullish coalescing and optional chaining operators

Now, coming back to the problem at hand, the best way to create our newData variable from this new version of data is to combine the nullish coalescing and optional chaining operators.

I guess at this point all of you would already know how to do it, but I'll still provide the code here.

for (const item of data) {
  newData[`${item.name} morningReading`] =
    item.morningReading?.reading ?? "No Data";
  newData[`${item.name} eveningReading`] =
    item.eveningReading?.reading ?? "No Data";
}
console.log(newData);

/* Prints
{
  'Voltage 1 morningReading': 10,
  'Voltage 1 eveningReading': 25,
  'Voltage 2 morningReading': 'No Data',
  'Voltage 2 eveningReading': 'No Data',
  'Voltage 3 morningReading': 0,
  'Voltage 3 eveningReading': 'No Data'
}
*/
Enter fullscreen mode Exit fullscreen mode

That's all!

To summarize, in this article we have seen what falsy and nullish values are and 5 ways in which we can add a check for them.

Now if you ask me which is the best method out of these five I have mentioned, I honestly cannot answer that because I believe there is no "one method" that is the best solution to all kinds of problems.
What might be the best method for one type of problem could end up being the worst one for another type of problem.
So all I can say is, look at your problem closely, think about what you are trying to achieve and choose a method that you think is the most suitable.

I really hope this post was helpful and if I have made any mistakes, please do let me know, I'll correct them. And if you know any other methods to check for falsy and nullish values, do share them in the comments.

Thank you so much for reading!

P.S. This is my first post here in dev.to, so any suggestions on how I can improve the quality of my posts are also welcome!

Top comments (4)

Collapse
 
tracygjg profile image
Tracy Gilmore

The condition item.reading !== undefined && item.reading !== null can be simplified if you are willing to take advantage of the (non-strict) Equality Operator algorithm that returns true when the value is undefined or null. This means null == undefined so item.reading != undefined is equivalent to item.reading !== null. One of the few cases when the == is more useful than ===.

Collapse
 
anuva312 profile image
Anusree V A • Edited

Yes, that is a very useful tip, thank you so much for sharing.
I have updated my post with the changes you have suggested!

Collapse
 
jonrandy profile image
Jon Randy πŸŽ–οΈ • Edited

Sometimes, the program won't throw any errors but there might be unexpected behavior. For example:

const a = null;
const b = "hello";
console.log(a+b); // prints "nullhello"
Enter fullscreen mode Exit fullscreen mode

Not exactly want we wanted, is it?

Well, what did you want? This isn't unexpected behaviour at all. It would only be unexpected if you don't understand how JS works.

Collapse
 
anuva312 profile image
Anusree V A

What I meant was if we write code expecting the data to always have valid values (especially if we are getting the data from some API) and if the data ends up having some null or undefined values, there might be some unexpected behavior or errors.

But I see the example I used was quite bad. Thanks for pointing it out.

I have edited the example, hope the new one makes sense!