PhoenixDAO Airdrop

PhoenixDAO is a project that has been started by Hydro community members to bring true decentralization through a fork of the protocols. This includes adding a community based DAO which will oversee…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Handling null and undefined in JavaScript

One aspect of JavaScript development that many developers struggle with is dealing with optional values. What are the best strategies to minimize errors caused by values that could be null, undefined, or otherwise uninitialized at runtime?

Some languages have built-in affordances for those circumstances. In some statically typed languages, you can say that null and undefined are illegal values, and let your programming language throw a TypeError at compile time, but even in those languages, that can't prevent null inputs from flowing into the program at runtime.

To get a better handle on this problem, we need to understand where these values can come from. Here are some of the most common sources:

I always pass inputs I receive from the network, database, or user input through a hydrating function. For example, I’ll use redux action creators that can handle undefined values to hydrate user records:

Sometimes, you’ll need to display different things depending on the current state of the data. If it’s possible to display a page before all of the data is initialized, you may find yourself in that situation. For example, when you’re displaying money balances to a user, you could accidentally display a $0 balance before the data loads. I’ve seen this upset users a number of times. You can create custom data types which generate different outputs based on the current state:

The code above is a state machine which makes it impossible to display invalid states. When you first create the balance, it will be set to an uninitialized state. If you try to display a balance while the state is uninitialized, you’ll always get a placeholder value ("--") instead.

To change that, you have to explicitly set a value by calling the .set method, or the setBalance shortcut we defined below the createBalance factory.

The state itself is encapsulated to protect it from outside interference to make sure that other functions can’t grab it and set it to an invalid state.

In your own functions, you can avoid creating null or undefined values to begin with. There are a couple ways to do that built into JavaScript that spring to mind. See below.

I never explicitly create null values in JavaScript, because I never really saw the point of having two different primitive values that essentially mean "this value does not exist."

Since 2015, JavaScript has supported default values that get filled in when you don’t supply a value for the argument or property in question. Those defaults don’t work for null values. That is usually a bug, in my experience. To avoid that trap, don’t use null in JavaScript.

If you want special cases for uninitialized or empty values, state machines are a better bet. See above.

There are a couple of features that can help you deal with null or undefined values. Both are stage 3 proposals at the time of this writing, but if you're reading from the future, you may be able to use them.

As of this writing, optional chaining is a stage 3 proposal. It works like this:

Also a stage 3 proposal to be added to the specification, “nullish coalescing operator” is basically a fancy way of saying “fallback value operator”. If the value on the left is undefined or null, it evaluates to the value on the right. It works like this:

If the future hasn’t arrived, yet, you’ll need to install @babel/plugin-proposal-optional-chaining and @babel/plugin-proposal-nullish-coalescing-operator.

If a function may not return with a value, it might be a good idea to wrap it in an Either. In functional programming, the Either monad is a special abstract data type that allows you to attach two different code paths: a success path, or a fail path. JavaScript has a built-in asynchronous Either monad-ish data type called Promise. You can use it to do declarative error branching for undefined values:

You could write a synchronous version of that if you want, but I haven’t needed it much. I’ll leave that as an exercise for you. If you have a good grounding in functors and monads, the process will be easier. If that sounds intimidating, don’t worry about it. Just use promises. They’re built-in and they work fine most of the time.

Arrays implement a map method which takes a function that is applied to each element of the array. If the array is empty, the function will never be called. In other words, Arrays in JavaScript can fill the role of Maybes from languages like Haskell.

A Maybe is a special abstract data type that encapsulates an optional value. The data type takes two forms:

Here’s the gist of the idea:

This is just an example to demonstrate the concept. You could build a whole library of useful functions around maybes, implementing other operations like flatMap and flat (e.g., to avoid Just(Just(value)) when you compose multiple Maybe-returning functions). But JavaScript already has a data type that implements a lot of those features out-of-the-box, so I usually reach for that instead: The Array.

If you want to create a function which may or may not produce a result (particularly if there can be more than one result), you may have a great use-case to return an array.

I find the fact that map won't be called on an empty list very useful for avoiding null and undefined values, but remember, if the array contains null and undefined values, it will call the function with those values, so if the function you're running could produce null or undefined, you'll need to filter those out of your returned array, as demonstrated above. That could have the effect of changing the length of the collection.

In Haskell, there’s a function maybe that (like map) applies a function to a value. But the value is optional and encapsulated in a Maybe. We can use JavaScript's Array data type to do essentially the same thing:

maybe takes a fallback value, then a function to map over the maybe array, then a maybe array (an array containing one value, or nothing), and returns either the result of applying the function to the array's contents, or the fallback value if the array is empty.

For convenience, I’ve also defined a toMaybeArray function, and curried the maybe function to make it most obvious for this demonstration.

He enjoys a remote lifestyle with the most beautiful woman in the world.

Add a comment

Related posts:

Recently viewed implementation using Redis as cache

If you have ever visited any major Ecommerce website, there is a 100% chance you have seen your viewed products again stacked in a panel. It’s almost as if the website is keeping track of your interests, well you are not crazy...

How To Hire Mobile App Developer USA

Want to hire mobile app developer USA? Hmm! The most tedious task is to hire dedicated mobile app developers that fit perfectly in your shoes. We are living in an era where most of the business…

The House With The Gravel Driveway

I remember our first house, we built and I was so very proud of that fact. The first time we visited the construction site, I thought to myself “those guys must be nervous seeing us come down. The…