What is the best method to check if a JavaScript variable has been initialized or defined? The variable could contain any data type (string, number, object, function, etc.). Which of these approaches is more correct or recommended:
if (elem) { // or !elem
or
if (typeof elem !== 'undefined') {
or
if (elem != null) {
The best method to check if a JavaScript variable has been initialized or defined depends on your specific use case, but generally if (typeof elem !== 'undefined') is the most reliable approach for checking initialization status, while if (elem != null) provides a good balance for checking both initialization and null values, and if (elem) works well for checking truthiness when you want to skip falsy values.
Contents
- Understanding Variable States in JavaScript
- Truthy/Falsy Checks:
if (elem) - Typeof Checks:
if (typeof elem !== 'undefined') - Null Comparison:
if (elem != null) - Comparative Analysis of Approaches
- Best Practices and Recommendations
- Common Pitfalls and Edge Cases
Understanding Variable States in JavaScript
JavaScript variables can exist in several states that affect how they should be checked:
- Declared but not initialized:
let elem;- variable exists but has valueundefined - Assigned a value:
let elem = 'value';- variable exists with a specific value - Not declared: Attempting to access
elemwhen it doesn’t exist at all will throw aReferenceError - Assigned
null:let elem = null;- variable exists with explicitnullvalue - Assigned
undefined:let elem = undefined;- variable exists with explicitundefinedvalue
Understanding these states is crucial because different checking methods treat them differently.
Important: In JavaScript, there’s a difference between a variable that doesn’t exist at all versus one that exists but holds the value
undefined. This distinction is fundamental to choosing the right checking method.
Truthy/Falsy Checks: if (elem)
The truthy/falsy approach uses JavaScript’s coercion rules to determine if a variable should be considered “true” or “false” in a boolean context.
// Examples of falsy values
if (false) {} // false
if (0) {} // false
if ('') {} // false
if (null) {} // false
if (undefined) {} // false
if (NaN) {} // false
// Examples of truthy values
if (true) {} // true
if (1) {} // true
if ('text') {} // true
if ({}) {} // true
if ([]) {} // true
if (function() {}) {} // true
Advantages:
- Concise and readable
- Automatically handles multiple “empty” states
- Works for checking if a variable has a “meaningful” value
Disadvantages:
- Treats
0andfalseas “false”, which might not be what you want - Cannot distinguish between
undefinedandnull - Will throw
ReferenceErrorif variable doesn’t exist
// Problem: Variable doesn't exist
if (nonExistentVar) {
// Throws ReferenceError
}
// Problem: 0 is falsy but might be valid
let count = 0;
if (count) {
// Won't execute, but count might be valid
}
According to MDN documentation, this approach works well when you want to check if a variable has a “meaningful” value, but it’s not suitable for checking initialization status.
Typeof Checks: if (typeof elem !== 'undefined')
The typeof operator returns a string indicating the type of the unevaluated operand. This is the most reliable method for checking if a variable has been declared and initialized.
// Safe for undeclared variables
if (typeof nonExistentVar !== 'undefined') {
// Works fine, no error
}
// Different cases
let declared;
let initialized = 'value';
let explicitNull = null;
let explicitUndefined = undefined;
if (typeof declared !== 'undefined') {
// false - declared but undefined
}
if (typeof initialized !== 'undefined') {
// true - declared and has value
}
if (typeof explicitNull !== 'undefined') {
// true - declared and has null value
}
if (typeof explicitUndefined !== 'undefined') {
// true - declared and has undefined value
}
Advantages:
- Safe for undeclared variables - won’t throw
ReferenceError - Precise - distinguishes between declared and undeclared variables
- Consistent - works the same regardless of variable scope
Disadvantages:
- More verbose than other methods
- Doesn’t check the actual value, just that it’s not
undefined - Might seem overly strict if you want to include
nullas “undefined”
As JavaScript.info explains, typeof is the only operator that can safely be applied to undeclared variables without throwing an error.
Null Comparison: if (elem != null)
This approach uses loose equality (!=) to check if a variable is neither null nor undefined.
let declared;
let initialized = 'value';
let explicitNull = null;
let explicitUndefined = undefined;
if (initialized != null) {
// true - has a value
}
if (explicitNull != null) {
// false - is null
}
if (explicitUndefined != null) {
// false - is undefined
}
if (declared != null) {
// false - is undefined
}
Important: This uses loose equality (!=), not strict equality (!==). The expression x != null is equivalent to x !== null && x !== undefined.
Advantages:
- Checks both
nullandundefinedin one expression - More concise than separate checks
- Still safe for declared variables
Disadvantages:
- Will throw
ReferenceErrorif variable doesn’t exist - Uses loose equality which might have unexpected behavior with other types
- Less explicit about what you’re checking for
This approach is recommended by many JavaScript developers as a good compromise when you want to treat both null and undefined as “empty” states.
Comparative Analysis of Approaches
Let’s compare the three approaches across different scenarios:
| Variable State | if (elem) |
if (typeof elem !== 'undefined') |
if (elem != null) |
|---|---|---|---|
| Not declared | ❌ ReferenceError | ✅ Safe (false) | ❌ ReferenceError |
let x; (undefined) |
❌ false | ❌ false | ❌ false |
x = null |
❌ false | ✅ true | ❌ false |
x = undefined |
❌ false | ❌ false | ❌ false |
x = 0 |
❌ false | ✅ true | ✅ true |
x = false |
❌ false | ✅ true | ✅ true |
x = '' |
❌ false | ✅ true | ✅ true |
x = 'text' |
✅ true | ✅ true | ✅ true |
x = {} |
✅ true | ✅ true | ✅ true |
x = [] |
✅ true | ✅ true | ✅ true |
x = function() {} |
✅ true | ✅ true | ✅ true |
Key Insights:
typeofis the only method that works safely with undeclared variablesif (elem)is the most restrictive, treating many valid values as “false”if (elem != null)provides a middle ground, treating onlynullandundefinedas “false”
Best Practices and Recommendations
When to Use Each Approach
Use if (typeof elem !== 'undefined') when:
- You need to check if a variable has been declared at all
- You want to distinguish between declared and undeclared variables
- You’re working with global variables or variables from different scopes
- You need the most precise initialization checking
// Example: Checking if a global variable exists
if (typeof globalVar !== 'undefined') {
// Safe to use globalVar
}
Use if (elem != null) when:
- You want to treat both
nullandundefinedas “empty” - You’re working with variables that you know exist
- You want a concise way to check for meaningful values
// Example: API response handling
if (response.data != null) {
// response.data exists and is not null/undefined
processData(response.data);
}
Use if (elem) when:
- You specifically want to check for truthy values
- You want to skip falsy values but consider
0,false, and''as valid - You’re working with variables that definitely exist
// Example: Checking if a user is logged in
if (user.isLoggedIn) {
// User is logged in, even if isLoggedIn is false (explicitly set)
}
Advanced Patterns
Optional chaining with nullish coalescing (ES2020+):
// Modern approach for safe property access
const value = obj?.prop ?? 'default';
Default parameter values:
function process(data = {}) {
// data will be {} if undefined, but null will pass through
}
Explicit checking with in operator:
// Check if property exists in object
if ('prop' in obj) {
// Property exists, even if value is undefined
}
Common Pitfalls and Edge Cases
ReferenceError with Undeclared Variables
// ❌ This will throw ReferenceError
if (nonExistentVar) {
// Error!
}
// ✅ Safe approach
if (typeof nonExistentVar !== 'undefined') {
// Works fine
}
Confusing Loose vs Strict Equality
// ❌ Loose equality can be confusing
if (elem != null) {
// This is really elem !== null && elem !== undefined
}
// ✅ More explicit
if (elem !== null && elem !== undefined) {
// Clearer intent
}
Shadowing Issues
let elem = 'value';
function check() {
// ❌ This checks the local variable, not the global one
if (elem) {
// Always true in this scope
}
// ✅ Still checks local variable
if (typeof elem !== 'undefined') {
// Also always true in this scope
}
}
Performance Considerations
// For performance-critical code, typeof might be slightly faster
// But the difference is negligible in most cases
// ❌ Multiple checks
if (elem !== null && elem !== undefined) {
// Two comparisons
}
// ✅ Single typeof check
if (typeof elem !== 'undefined') {
// One comparison
}
Conclusion
-
For checking initialization status: Use
if (typeof elem !== 'undefined')- it’s the most reliable and safe method that won’t throw errors for undeclared variables. -
For checking meaningful values: Use
if (elem != null)- it provides a good balance by treating bothnullandundefinedas “empty” states while being more concise than separate checks. -
For truthy value checks: Use
if (elem)- this works well when you want to skip falsy values but consider0,false, and''as potentially valid. -
Consider modern alternatives: Optional chaining (
?.) and nullish coalescing (??) provide elegant solutions for many common scenarios in modern JavaScript.
The choice ultimately depends on your specific use case and what you’re trying to achieve with the variable check. Always consider whether you need to handle undeclared variables, how you want to treat null vs undefined, and whether you’re checking for truthiness or just existence.