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…
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:
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.
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
If you are used to using let like me, you will get something different:
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:
"use strict";
Strict mode will prevent us from defining undefined:
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:
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”? But there is one little downside:
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:
;( 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
And this is a huge problem. Now when you are writing your if statements like so:
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
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
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
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
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
no-shadow-restricted-names - Rules
Summary
- Try not to use the undefined keyword. It’s not recommended to do so.
-
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. - Using linters (e.g. ESLint) will prevent you from setting values to undefined, so you don’t have to worry about it.
- In edge cases, you may need to set undefined just to make sure it’s undefined.
Top comments (3)
For me, it seems that
undefined
only exists for out-of-index Arrays and Objects, instead of throwing an error. Exists for compatibility reasons.Related, undefined is a primitive.
The title literally had my tears, only Javascript begs such a question to be answered.
Love it.
Thank you!