In JavaScript, is undefined actually undefined?
Tags: javascript, beginners, webdev, node
Published: 2020-04-04 17:32:21

It should be, but it turns out that *undefined* is a variable. So what happens if we set a value to it? The weird world of JavaScript…

![Thumbnail](https://miro.medium.com/max/1400/1*t0ebm5qG0t6z7vVDh2NX4A.jpeg)

>**TL;DR** undefined is not a restricted keyword so we can name by mistake our variable *undefined* and set a value to it which will cause bugs during a runtime. Use linters to prevent it from happening.

There is a good reason for using *void* keyword instead of *undefined* in your if statements and this is because *undefined* variable actually might be defined. The reason behind it is not a restricted keyword. *Undefined* is a property of the global object, so it's a variable in a global scope. Go ahead and type window in your browser console - you will find "undefined" property inside the window object. So:

```js
window.undefined === undefined; // returns true
```

##**What's a *void* in JavaScript?**
In simple words: void in JS is an operator used to return *undefined* value.

```js
void 0 == void(0); //true because void 0 is equal to void(0)
void 1 == void(0); //true
void 0 == undefined; //true
void 0 === undefined; //true
void 1241 === void "everything can go here" //true
```

The above code shows that the void keyword is the best choice when it comes to checking variables for an undefined value.

>**Disclaimer:** at the beginning of the article I wrote that undefined might be defined. That means in some cases "void 0 === undefined" might return false. We will go back to this issue shortly.

##What will happen if I define "undefined"?
In modern browsers (including IE11) which support ECMA-262 5th version from 2009 also known as ES5, such a variable still will be undefined because it's read-only.

>
15.1 The Global Object
The unique global object is created before control enters any execution context.
Unless otherwise specified, the standard built-in properties of the global object have attributes `{[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}`.
[...]
15.1.1.3 undefined
The value of undefined is undefined (see 8.1). This property has the attributes `{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }`.

**Source:** [ECMAScript Language Specification](https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262%205th%20edition%20December%202009.pdf)

![Console](https://miro.medium.com/max/1400/1*qOWGmx1OagOy-ZvTObN8Cw.png)

If you are used to using *let* like me, you will get something different:

![Console](https://miro.medium.com/max/1400/1*3Yz1FVkn9HuTLjMJDLz7fg.png)

We get the `Identifier 'undefined' has been declared` because it was defined - inside a window object. But shouldn't we get an error when we use *var* anyway? We should! That's why it's good to type at the beginning of each .js file:
```js 
"use strict";
```

Strict mode will prevent us from defining *undefined*:

![Console](https://miro.medium.com/max/1400/1*lvXKVNIEVHUvFD8KzDf8jA.png)

##**I want to name my variable “undefined” anyway.**

There is a trick. The above rule specified in 15.1.1.3 **applies only to global objects.** Local scopes are different:

```js
function someFunction() {
   let undefined = 10;
   console.log(undefined);
}
someFunction(); //logs 10
```

ES6 standard introduced new *let* and *const* keywords. Variables declared by *var* keyword are scoped to the immediate function body (hence the function scope) while *let* variables are scoped to the immediate enclosing block denoted by `{ }` . **Source:** [What’s the difference between using “let” and “var”?](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var) But there is one little downside:

![Console](https://miro.medium.com/max/1190/1*L_m8qSwT1BqA8aG_wzilrQ.png)

There is a reason to set a value to undefined. In a jQuery *undefined* is specified as a parameter to make sure it wasn’t defined before, for example in other included in project script:

[jquery.boilerplate.js](https://github.com/jquery-boilerplate/jquery-boilerplate/blob/a270f97ba531ecf52de280bdb3ea56d3c8c0122b/src/jquery.boilerplate.js)

```js
;( function( $, window, document, undefined ) { ... }

```
>*undefined isn’t really being passed in so we can ensure the value of it is truly undefined. In ES5, undefined can no longer be modified.*

##**How about Node.js?**
**Turns out we can set a value to undefined in node.js environment as well.** But Node.js Supports ES5 so what‘s going on here?

The answer can be found in official Node.js docs:

>In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different. **The top-level scope is not the global scope**; var something inside a Node.js module will be local to that module.

**Source:** [Node.js v13.11.0 Documentation](https://nodejs.org/api/globals.html#globals_global_objects)

And this is a huge problem. Now when you are writing your if statements like so:
```js
if (myVariable === undefined) {...}
```
… you can’t be sure if your variable will be undefined because somebody could have named by mistake, a variable “undefined” tens of lines earlier.

##**Then how to determine if the variable is undefined?**
There are multiple ways to do that:
- using null
```js
var something;
something == null; // true
something === null; // false
```
I don’t like this way because null is not null in JavaScript but is an object, and you have to remember to use ==, not === which nowadays is not recommended or typical.
- typeof
```js
var something;
typeof something === 'undefined'; // true
typeof something === undefined; // false
```
Typeof always returns a string. Back in times when I was a beginner in JavaScript, making my first lines of code it wasn’t obvious for me why I should check for undefined with a string. For this reason, I don’t like doing so but it’s recommended in ESLint so this is an option as well.

- check if the variable has a value

```js
var something;
if(something) console.log("is not undefined");
```
Although it will work I wouldn’t recommend it, because variable something could be set to false which means it has a value and is not undefined anymore.

- void 0
```js
var something;
void 0 == something; // true
void 0 === something; // true
```

I think this is the best way. There is not much to remember because void 0 is always undefined. It looks unusual but it does its job and is easy to type.

##**No-undefined / no-shadow-restricted-names in ESLint**

ESLinter comes with no-undefined and no-shadow-restricted-names rules, which enforces us, to not use *undefined* anywhere. For this reason (and not only) it’s good to use code linters. You can read more about these rules here:
[no-undefined - Rules](https://eslint.org/docs/rules/no-undefined)
[no-shadow-restricted-names - Rules](https://eslint.org/docs/rules/no-shadow-restricted-names)

#**Summary**
1. Try not to use the *undefined* keyword. It’s not recommended to do so.
2. `Void 0` is good because it’s the most reliable and easy way to determine if variable is undefined or not. Typeof works fine too. It’s totally up to you which option you prefer more.
3. Using linters (e.g. ESLint) will prevent you from setting values to undefined, so you don’t have to worry about it.
4. In edge cases, you may need to set undefined just to make sure it’s undefined.