On a Bias Against Null in Javascript
Tags: javascript, programming
Published: 2021-10-13 18:01:49

---
title: On a Bias Against Null in Javascript
published: true
date: 2021-10-01 20:01:08 UTC
tags: javascript, programming
canonical_url: https://www.split.io/blog/bias-against-null-javascript/
---

JavaScript is an unusual programming language in that it has two null-like values: `undefined` and `null`. These are distinct values (`null` !== `undefined`). They are also different data types in JavaScript, among the primitive types are `string`, `number`, `boolean`, `null` and `undefined`.

After a couple of years of working with JavaScript, I came to the conclusion that `null` is pretty problematic and should be avoided when writing JavaScript whenever possible. I’ve since spent several years writing both Node.js and various browser-based JavaScript applications without using `null` (except for converting to or from undefined. e.g. `if (funcReturnValue === null) { funcReturnValue = undefined; }`), and have found it to be a viable and desirable approach to take.

Before discussing why it seems better to avoid `null`, let’s first talk about how these values, `undefined` and `null` get into your application’s data flows to start with.

## Where Undefined and Null Come From

`undefined` is omnipresent in JavaScript. If you declare a variable without an explicit value assigned to it, it gets the value `undefined`:

`let myVariable; // myVariable is undefined`

If you do not pass a parameter to a function, and you access that parameter in the function, it will have the value `undefined`:

```
function myFunction(a) {
   console.log(a);
}

myFunction(); // this will print out "undefined"
```

If your function returns nothing, and the return value is assigned to a variable, that variable will receive the value `undefined`

```
function myFunction() {
  // do nothing!
}

let myVariable = myFunction(); // myVariable will have the value undefined.
```

If you access an element of an array that has nothing in it, you will also get `undefined`.

```
let myArray = [1, 2];

let myVariable = myArray[5]; // myVariable is now undefined
```

Naturally, you can also explicitly set something to undefined:

`let myVariable = undefined;`

While there are other obscure ways to generate undefined, such as `let myVariable = void 0`, the previously listed cases are the most common ways.

In contrast, `null` never comes as a result of no value being assigned to a variable or parameter. You must always explicitly set something to `null`. This happens either through an explicit assignment:

`let myVariable = null;`

Calling a browser function that returns `null`:

`let myVariable = localStorage.getItem('aKeyThatDoesNotExist');`

Or deserialization a JSON value

`let myVariable = JSON.parse('{"a":null}').a;`

## Why it is Desirable to Avoid Null

1. Supporting both `null` and `undefined` creates more work  
If you are routinely operating with both `null` and `undefined` in the data flows in your application, you are forced to do one of three things:

You must be studiously aware of which value is going through each data flow in your application.  
This is unrealistic in all but the most trivial of applications. (See the note about TypeScript below)  
You must routinely be checking for both in your data flows. e.g. `if (myValue === undefined || myValue === null) { …`  
This makes your code harder to read.  
You must use the regular equality operators (e.g. `if (myValue != null) { …`, rather than the type-safe equality operators (e.g. `if myValue !== null ...` )  
This is definitely a risky pattern. There are eslint rules that can help you do the right thing here (e.g. `’eqeqeq’: [“error”, “always”, {“null”: “ignore”}] ), but at best this introduces what your eyes will see as unnecessary variability in your code. At worst (if you are not using eslint’s rule), it will introduce bugs that you will overlook in code reviews.

### Supporting only `null` is not easy

Because `undefined` is so extremely easy to introduce into your data flows, it takes substantial work to keep it out. If the goal is to get the highest quality of code with the minimal amount of work, this is not a good candidate for meeting that goal.

### Supporting only `undefined` is not hard

In practice, it is easy to capture the `null` values any time that they would get introduced into your code and immediately switch that value to undefined. e.g. for function return values you can do something like:

`let myValue = localStorage.get('aKeyThatDoesnotExist') || undefined;`

For both browser and third party API’s, you can often figure out if a function returns (or expects) `null` from the documentation and convert, as above (though, you do need to be careful because both `''` (empty string) and `false` will also be converted to `undefined` in the example above). If there are TypeScript definitions for your library, that can also help considerably, since TypeScript can make explicit the types libraries use. One common case is dealing with JSON data structures (unlike JavaScript, JSON has no notion of `undefined`). But a simple conversion routine solves this:

```
let replaceValues = (data, oldValue, newValue) => {
 if (Array.isArray(data)) {
   return data.map(element => replaceValues(element, oldValue, newValue));
 }

 if (typeof data === 'object' && data !== null) {
   return Object.entries(data).reduce((prev, [key, value]) => {
     return {
       ...prev,
       [key]: replaceValues(value, oldValue, newValue),
     };
   }, {});
 }

 return data === oldValue ? newValue : data;
};
```

Similar things can be done for return values from third-party functions.

### Null doesn’t trigger default values

If you have a function `function myFunction(x = 5)`, when you call `myFunction()` or `myFunction(undefined)`, then `x` will be set to 5. But if you call `myFunction(null)`, then `x` will be set to `null`. If you have variables that could be indiscriminately set to either `null` or `undefined` (a situation which is very likely if you are allowing both into your application code), these default values will not always be applied as you are likely to want them to be applied.

On the other hand, if you are treating `null` and `undefined` distinctly, then you may actively find it useful to be able to not get that default value by deliberately passing `null`. But as mentioned elsewhere, the effort to make this safe doesn’t seem like a good tradeoff to make.

### `typeof null === 'object'`

One of the most frustrating things about `null` is that `typeof null === 'object'`. This means that if you do allow `null` into your data flows, when you do `typeof` on any variable that might receive `null`, you must check whether an `object` result means `null` or some form of `{ … }`.  
Similarly, if you are checking whether something is an object, you must then make sure it isn’t a `null` before you dereference it.

`undefined` has none of these problems, since `typeof myValue === 'undefined'` is not ambiguous.

### A note about TypeScript

If you use TypeScript and use it with a great deal of discipline, it is much more realistic to manage both `null` and `undefined` flowing through your application. However, what this will also create for you is many situations where some data structures have `null` values in one part of the application, and their equivalents in other parts of the application will have `undefined`. Because these will collide and conflict, you’ll either end up with type declarations like `myProperty: null | undefined` or you will end up having to do a lot of data conversions at various unpredictable places in your application. In the end, while the explicit treatment of these types is a big improvement over JavaScript, the hassle factor remains unchanged (or even worse). Even with TypeScript, then, it still seems better to simply keep `null` out of the data flows in your application.

### Conclusion

Because `undefined` is, effectively, unavoidable, because `null` is pretty easy to keep out of the data flows in an application, and because the code is simpler by not needing to manage both data types, I’ve found it more productive just to ignore the existence of `null` except at necessary interface boundaries where we simply convert to `undefined`.

## What to Read Next

I hope you enjoyed reading our article, “On a Bias Against Null in JavaScript.” Here are some other posts you might enjoy:

- [Build a CRUD App With Spring Boot and Angular in 20 Minutes](https://www.split.io/blog/crud-app-spring-boot-angular/) 
- [Take Your JavaScript Skills Mobile with React Native](https://www.split.io/blog/react-native-tutorial/) 
- [Set Up Feature Flags with React in 10 Minutes](https://www.split.io/blog/react-feature-flags-10-minutes/) 

For more great content, follow us on [YouTube](https://www.youtube.com/channel/UCrkFMZZY8cjmZyKzOVV245Q) and [Twitter](https://twitter.com/SplitSoftware)! You can also join the Split Community on [Slack](https://try.split.io/join-community).