DEV Community

Cover image for The Difference Between Null and Undefined in JavaScript
Zahra Khan
Zahra Khan

Posted on • Updated on • Originally published at blog.zahrakhadijha.com

The Difference Between Null and Undefined in JavaScript

Whenever I encounter null or undefined, I get incredibly confused by how each data type is used in JavaScript.

I mean, what's the difference? Don't they both express the concept of nothing?
Giphy

I decided to do some research to gain a deeper understanding of the two data types. It's helpful to have this knowledge so that you can use them correctly when needed. I've also learned that sometimes, the difference between null and undefined comes up in interviews. 👀

Introduction

JavaScript has 7 primitive data types, two of which are null and undefined.

Null is an assignment value, which means that you can assign the value null to any variable when you want that variable to be empty. It is intentionally left blank and will point to an empty value.

let hasCat = null;
// nullish
Enter fullscreen mode Exit fullscreen mode

Undefined is a variable that exists but hasn't been initialized YET. Which means that later, I can come back to my variable and assign it a value that it did not have before. So if I declare a variable without a value, it's just considered non-initialized.

let currentJob;
// undefined
Enter fullscreen mode Exit fullscreen mode

The way that I understood both of them is that, yes, they are both very similar in that they both don't have a value that you're trying to access. If you were to compare the two in JavaScript, implicitly they're the same because JavaScript considers them both as empty values. But since they are both different data types, if you compare them explicitly, they will result in a falsey value.

null == undefined; 
// truthy

null === undefined;
// falsey

Enter fullscreen mode Exit fullscreen mode

Analogy

Imagine you're moving. You bought a bunch of boxes. You have to pack up your stuff and put them inside of those boxes. But you're disorganized so you forget to label what's in the boxes. You have 5 boxes that are full of things and you have 2 boxes that are left empty. You want to label your boxes but you've already put tape on them, so you tell yourself you'll come back to it later. For now the 5 boxes are TBD. And the 2 boxes are leftover and empty. In code, that would look like:

let fiveBoxes = undefined;
let twoBoxes = null;
Enter fullscreen mode Exit fullscreen mode

The five boxes with a bunch of stuff in them are considered undefined because they have things in them but you don't know what's in it YET. The two boxes left empty are MEANT to not have anything in them.

Null vs. Undefined

The difference between the two data types is:

Undefined

  • Declared
  • Uninitialized
  • Engine Assigned

Null

  • Lack of
  • Empty/void
  • Non-existent
  • User assigned

Go to your console, and type in:

typeof null
typeof undefined
Enter fullscreen mode Exit fullscreen mode

What do you get?

Conclusion

Null and undefined are not the same. It's important to learn the difference between the two so you avoid any buggy behavior in your code and have a clear understanding of why they exist. It's also cool if you're able to clearly state the difference in an interview too 😉

Feel free to hit me up on Twitter if you're still confused! Or if you'd just like to chat.

Top comments (26)

Collapse
 
apyrkh profile image
Aliaksandr

What about

const bar = { foo: undefined }
bar.foo === undefined 

// and this
const bar = {}
bar.foo === undefined 
Enter fullscreen mode Exit fullscreen mode

This is not the same, right? Also in the latest typescript it was implemented to differentiate these 2 cases.

I prefer null for nullish values.

Collapse
 
za-h-ra profile image
Zahra Khan

This is incredible feedback and so good to learn!

Yeah I've watched some videos on the topic where it's best practice to use undefined over null but I love your explanation!

Thank you!

Collapse
 
peerreynders profile image
peerreynders • Edited

One caveat about undefined:

const obj = {
  nil: null,
  nothing: undefined,
};

console.log(obj.nil == undefined);          // true  (non-strict equality)
console.log(obj.nothing === undefined);     // true
console.log(obj.zilch === undefined);       // true

console.log(obj.hasOwnProperty('nil'));     // true
console.log(obj.hasOwnProperty('nothing')); // true
console.log(obj.hasOwnProperty('zilch'));   // false

const array = [null, ,undefined];

console.log(array[0] == undefined);         // true  (non-strict equality)
console.log(array[1] === undefined);        // true
console.log(array[2] === undefined);        // true
console.log(array[3] === undefined);        // true

console.log(array.hasOwnProperty(0));       // true  (value `null`)
console.log(array.hasOwnProperty(1));       // false (hole, empty)
console.log(array.hasOwnProperty(2));       // true  (value `undefined`)
console.log(array.hasOwnProperty(3));       // false (out of bounds)
Enter fullscreen mode Exit fullscreen mode

An undefined value is inconclusive with regards to the existence of the property/element within an object/array.

Also note that browser developer tools will mark "holes" in arrays with empty.

Chromium:

> console.log([0,,2]);
    (3) [0, empty, 2]
Enter fullscreen mode Exit fullscreen mode

Firefox:

> console.log([0,,2]);
    Array(3) [ 0, <1 empty slot>, 2 ]
Enter fullscreen mode Exit fullscreen mode

ECMAScript 6: holes in Arrays


The void operator returns undefined.

let count = 0;
const result = void(count += 1);
console.log(count);  // 1
console.log(result);  // undefined
Enter fullscreen mode Exit fullscreen mode
 
analog_heart profile image
BP • Edited

Null is a valid value to represent anything that is nullable in nature. Undefined means it does not exist because it’s unset and was never set.

Does a person have a middle name? If yes, it will have an alpha value. If they do not have a middle name, it would be null. This is to say that the actual value is deliberately meant to be no middle name. This differs from undefined which is to say that the value does not exist because it was unset. Perhaps the form to enter the person details was only partially completed. Undefined means no deliberate choice has been applied to it. Null differs, if you’re using it correctly.

Taking this further, let’s say your data store is Mongo. You started by only collecting first and last name, and have thousands of documents that are missing this field. Later, you decide to include a middle name. Null is still valid, because not everyone has a middle name. You decide that, in order to facilitate data collection, you want to prompt any existing users that are missing this field. You could prompt those that have not yet taken an action because you can clearly see that the field is missing/undefined. They may choose to acknowledge that they have no middle name, at which point you’d save null to the document.

Now you want to integrate with a third party web api. That third party system is written in a strongly typed language (Java or C#). They only have the notion of null. You have forgotten to send over this middle name field because of how js’s type system works, and because of how the deserializers work, they do not know whether to reject the request or not. After all, they default to null if the field is not present in the json payload. The system has now made an incorrect assumption because of a limitation between being able to discern whether the data should be there but wasn’t or whether it was there and was intended to be null. This problem exists because there’s only one null.

Undefined is metadata that describes a js value that’s integral to its duck typing system. It’s got an entirely different purpose than null.

If you work in the field, how long have you been at it?

Collapse
 
analog_heart profile image
BP

Null and undefined are not the same and serve different purposes.

Collapse
 
michaelcurrin profile image
Michael Currin • Edited

Note that var and let keywords let you make undefined but const does not

let x

// syntax error
const y
Enter fullscreen mode Exit fullscreen mode

For bonus points, add a fallback for undefined or null or falsy (zero, empty string)

let x

const y = x || "default"
console.log(y.toUpperCase())
Enter fullscreen mode Exit fullscreen mode

Or in newer versions of JS, you can use this to handle null and undefined, but it won't replace zero or empty string.

let y

const x = y ?? "default"
Enter fullscreen mode Exit fullscreen mode

michaelcurrin.github.io/dev-cheats...

TypeScript can enforce missing values for you so you don't have to throw errors or use a fallback.

Collapse
 
za-h-ra profile image
Zahra Khan

I didn't even consider const. Thank you for pointing that out!

 
analog_heart profile image
BP

I cannot effectively respond as I’m in my phone.

If you filled a form partially, you can just use undefined.

Yes, it would be undefined by default. That’s my point.

Both mean "nullish/empty/missing value", making the distinction between intentionally left empty or not makes no sense.

They do not because one requires an action to be applied. Intent rather than an assumption. Null does not mean a missing value in the way you are describing. That is expressly the purpose of undefined in js.

You're basically describing a poorly designed API/back-end. If you have a back-end that doesn't have the concept of an optional/undefined property, then you should acomodate for that. Front-end shouldn't be fixing issues of the back-end (which is a pretty common mistake).

First - and my main point - is to point out the flaw in those languages that happens to not exist in js because js actually got something right. But secondly, do you often have control over the third party systems you integrate with? 🤔

If the middleName field becomes required, then you could say that if it isn't a string, then it wasn't filled yet (undefined), and if is intentionally left empty, then is just an empty string "", again no need for null here.

Apply this to an integer. Do you fallback to zero as default? You’re being too narrow in your reading.

I'm not the only one that says this, if you don't want to take my word for it, maybe you'll take the word of Douglas Crockford (the author of "JavaScript: The Good Parts" and JSON) here.

I’m aware of him, and he is not infallible. This is an example.

I don't know how is my time in this field relevant, but if you really want to know, I been doing this for 10+ years

It’s relevant because you keep citing “real world examples”, yet are advocating for lossy handling of data. It makes no sense and does not fit well with practical experience, imo.

 
llgcode profile image
llgcode

I agree 'Because when you use null you end up using both null and undefined, but when you use just undefined, you only check for one' I guess this is the main reason. Undefined is like optional for me and I never use null and undefined with different meaning in my code. I mean I don't have any example of code that treat it differently when having a variable or property with the type undefined or null. Thank to the strict option of typescript, I check every case.

Collapse
 
eljayadobe profile image
Eljay-Adobe

Another fun difference:

var v = void 0 // ... which is undefined
var u = undefined
var n = null
console.log(v === u) //> true
console.log(+u) //> NaN
console.log(+n) //> 0
Enter fullscreen mode Exit fullscreen mode
 
snawaz profile image
Sarfaraz Nawaz • Edited

The point with the number | boolean was that we don't need it to be number | null

Looks like you didn't read my post carefully. The point is, your point is WRONG. number | boolean is NOT the same as number | null. You cannot give a WRONG alternative as a replacement. Also, again, you do NOT understand "states with precision". In many places, X | undefined could mean the same thing as X | null if you do not require the precision. But when you need it, X | undefined is NOT sufficient. You have to INVENT something, which is precisely why you gave the examples of -1 and number | boolean. Both are WRONG. At least, number | "nothing" makes better sense!

So I said that as an example of how null is not necessary to express that theoretical "third state" for which you supposedly need null, and you took that as a way of saying that I endorse having four states.

See. I told you. You do NOT understand states. Your example has a FOURTH state as well.

and reducing the amount of nullish values to 1 or even 0 (with stuff like Haskell's Maybe) is way better than having two as JS has

You think Haskell has 0 nullish value? Maybe is exactly how Haskell implements a nullish value, or an absence of value, or a missing value. Just because it's spelled differently and accessed differently, does NOT mean it does not encapsulate the idea of nullish value. It's BETTER designed null.

Collapse
 
blindfish3 profile image
Ben Calder

Generally is seen as a bad practice to use both

That's the first time I've heard this. Do you have any evidence to back this up?

To my mind the distinction between the two is quite clear:

  • undefined: no value has yet been assigned
  • null: explicitly set to empty

In practice I agree they're interchangeable, but occasionally it's useful to be able to distinguish between a value that hasn't been set and one that has been explicitly emptied.

 
snawaz profile image
Sarfaraz Nawaz

but you could make it so "intentionally left blank" is a -1, or you have another property just to track that, or you make it number | boolean and let it as a false value, so many ways that don't require null.

Here you lost the argument! Because when you say anInteger? : number | boolean, you are actually trying to distinguish "missing by default" from "intentionally not set". Now you can express that in many ways:

anInteger? : number | boolean  // your suggestion, not mine!
// or
anInteger? : number | "not set" // better?
// or
anInteger? : number | "nothing" // better?
// or simply
anInteger? : number | null  // still better?
Enter fullscreen mode Exit fullscreen mode

All are equivalent now (well not really, not yours). You're simply choosing to "spell" null differently in each case. BTW, moreover, do you realize number | boolean does not make much sense? Do you know why? THINK. Because now you can have:

anInteger: 10
// or
anInteger: false // you mean "intentionally not set"?
// or 
anInteger: true  // what does it mean?
Enter fullscreen mode Exit fullscreen mode

I'm sure you didn't mean that? That is what happens when you do not understand "states" with precision. When you want to have 3 states (like number, undefined and null (or "nothing" if you spell it differently), your suggestion introduced a bug and you end up having 4 states.

 
analog_heart profile image
BP

Real world scenarios, they mean entirely different things.

Collapse
 
veadro profile image
Veadro

The more I learn about JavaScript's rich diversity of freedom the more I want to just stick with typescript.

Collapse
 
za-h-ra profile image
Zahra Khan

Yeah I can't wait to learn Typescript properly!

Collapse
 
michaelcurrin profile image
Michael Currin

Good point in other comment on filling in very common encounters of undefined as when getting a non-existent key from an object an getting undefined (in Ruby you get null and Python you get an error) and an argument that is not defined (Python will give an error when it is not defined but in JS you must validate yourself).

Also noteworthy for how to check for undefined.

const MY_VAR = process.env.MY_VAR

if (typeof MY_VAR === 'undefined') {
  throw new Error('Must set MY_VAR on environment variables')
}
Enter fullscreen mode Exit fullscreen mode
function foo(abc) {
 if (typeof abc === 'undefined') {
   throw new Error('abc is a required argument')
  }
  console.log(abc)
}

foo(123)
foo(null)
foo() // error
Enter fullscreen mode Exit fullscreen mode

Another use is to skip positional arguments by passing a value explicitly as undefined, assuming it is optional.

foobar("abc", undefined, 456)
Enter fullscreen mode Exit fullscreen mode

In Python this is not need as you can switch to keyword params.

foobar("abc", third_param=456)
Enter fullscreen mode Exit fullscreen mode
 
blindfish3 profile image
Ben Calder

I searched and didn't find much more than 'you can save some inconvenience by avoiding null' 🤷
I don't have a very strong opinion on this. I just hadn't seen anything that justified describing the use of null as bad practice. If there was I might have to speak to the backend devs I work with 😅