Reputation: 35781
Is there a universal JavaScript function that checks that a variable has a value and ensures that it's not undefined
or null
? I've got this code, but I'm not sure if it covers all cases:
function isEmpty(val){
return (val === undefined || val == null || val.length <= 0) ? true : false;
}
Upvotes: 3125
Views: 3077897
Reputation: 272006
This question has two interpretations:
Check if the variable has a value
Check if the variable has a truthy valueThe following answers both.
In JavaScript, a value could be nullish or not nullish, and a value could be falsy or truthy.
Nullish values are a proper subset of falsy values:
╭─ nullish ──────╮ ╭─ not nullish ─────────────────────────────────╮
┌───────────┬──────┬───────┬───┬────┬─────┬──────┬───┬─────────┬─────┐
│ undefined │ null │ false │ 0 │ "" │ ... │ true │ 1 │ "hello" │ ... │
└───────────┴──────┴───────┴───┴────┴─────┴──────┴───┴─────────┴─────┘
╰─ falsy ───────────────────────────────╯ ╰─ truthy ───────────────╯
Use one of the following depending on your coding style:
if (value == null) { /* value is nullish */ }
if (value === undefined || value === null) { /* value is nullish */ }
if (value == undefined) { /* value is nullish */ }
if ((value ?? null) === null) { /* value is nullish */ }
Notes:
==
operator works because it has a special case for null vs undefined comparison===
operator is more readable (opinion based), eqeqeq friendly and allows checking for undefined and null separatelynull
for straight forward comparisonif (value != null) { /* value is not nullish, although it could be falsy */ }
if (value !== undefined && value !== null) { /* value is not nullish, although it could be falsy */ }
if (value != undefined) { /* value is not nullish, although it could be falsy */ }
if ((value ?? null) !== null) { /* value is not nullish, although it could be falsy */ }
Use the !
operator:
if (!value) { /* value is falsy */ }
if (value) { /* value is truthy */ }
The nullish, falsy and truthy checks cannot be used for data validation on their own. For example, 0
(falsy) is valid age of a person and -1
(truthy) is not. Additional logic needs to be added on case-by-case basis. Some examples:
/*
* check if value is greater than/equal to 0
* note that we cannot use truthy check here because 0 must be allowed
*/
[null, -1, 0, 1].forEach(num => {
if (num != null && num >= 0) {
console.log("%o is not nullish and greater than/equal to 0", num);
} else {
console.log("%o is bad", num);
}
});
/*
* check if value is not empty-or-whitespace string
*/
[null, "", " ", "hello"].forEach(str => {
if (str && /\S/.test(str)) {
console.log("%o is truthy and has non-whitespace characters", str);
} else {
console.log("%o is bad", str);
}
});
/*
* check if value is not an empty array
* check for truthy before checking the length property
*/
[null, [], [1]].forEach(arr => {
if (arr && arr.length) {
console.log("%o is truthy and has one or more items", arr);
} else {
console.log("%o is bad", arr);
}
});
/*
* check if value is not an empty array
* using optional chaining operator to make sure that the value is not nullish
*/
[null, [], [1]].forEach(arr => {
if (arr?.length) {
console.log("%o is not nullish and has one or more items", arr);
} else {
console.log("%o is bad", arr);
}
});
Upvotes: 424
Reputation: 235962
You can just check if the variable has a truthy
value or not. That means
if (value) {
// do something..
}
will evaluate to true
if value
is not:
The above list represents all possible falsy
values in ECMA-/Javascript. Find it in the specification at the ToBoolean
section.
Furthermore, if you do not know whether a variable exists (that means, if it was declared) you should check with the typeof
operator. For instance
if (typeof foo !== 'undefined') {
// foo could get resolved and it's defined
}
If you can be sure that a variable is declared at least, you should directly check if it has a truthy
value like shown above.
Upvotes: 5767
Reputation: 120476
function isEmpty(value){
return (value == null || value.length === 0);
}
This will return true for
undefined // Because undefined == null
null
[]
""
and zero argument functions since a function's length
is the number of declared parameters it takes.
To disallow the latter category, you might want to just check for blank strings
function isEmpty(value){
return (value == null || value === '');
}
Null or whitespace
function isEmpty(value){
return (value == null || value.trim().length === 0);
}
Upvotes: 134
Reputation: 8131
I don't recommend trying to define or use a function which computes whether any value in the whole world is empty. What does it really mean to be "empty"? If I have let human = { name: 'bob', stomach: 'empty' }
, should isEmpty(human)
return true
? If I have let reg = new RegExp('');
, should isEmpty(reg)
return true
? What about isEmpty([ null, null, null, null ])
- this list only contains emptiness, so is the list itself empty? I want to put forward here some notes on "vacuousness" (an intentionally obscure word, to avoid pre-existing associations) in javascript - and I want to argue that "vacuousness" in javascript values should never be dealt with generically.
For deciding how to determine the "vacuousness" of values, we need to accomodate javascript's inbuilt, inherent sense of whether values are "truthy" or "falsy". Naturally, null
and undefined
are both "falsy". Less naturally, the number 0
(and no other number except NaN
) is also "falsy". Least naturally: ''
is falsy, but []
and {}
(and new Set()
, and new Map()
) are truthy - although they all seem equally vacuous!
There is also some discussion concerning null
vs undefined
- do we really need both in order to express vacuousness in our programs? I personally avoid ever having undefined
appear in my code. I always use null
to signify "vacuousness". Again, though, we need to accomodate javascript's inherent sense of how null
and undefined
differ:
undefined
undefined
:let f = a => a;
console.log(f('hi'));
console.log(f());
undefined
, not null
:let f = (v='hello') => v;
console.log(f(null));
console.log(f(undefined));
To me, null
is an explicit signifier of vacuousness; "something that could have been filled in was intentionally left blank".
Really undefined
is a necessary complication that allows some js features to exist, but in my opinion it should always be left behind the scenes; not interacted with directly. We can think of undefined
as, for example, javascript's mechanic for implementing default function arguments. If you refrain from supplying an argument to a function it will receive a value of undefined
instead. And a default value will be applied to a function argument if that argument was initially set to undefined
. In this case undefined
is the linchpin of default function arguments, but it stays in the background: we can achieve default argument functionality without ever referring to undefined
:
This is a bad implementation of default arguments as it interacts directly with undefined
:
let fnWithDefaults = arg => {
if (arg === undefined) arg = 'default';
...
};
This is a good implementation:
let fnWithDefaults = (arg='default') => { ... };
This is a bad way to accept the default argument:
fnWithDefaults(undefined);
Simply do this instead:
fnWithDefaults();
By the way: do you have a function with multiple arguments, and you want to provide some arguments while accepting defaults for others?
E.g.:
let fnWithDefaults = (a=1, b=2, c=3, d=4) => console.log(a, b, c, d);
If you want to provide values for a
and d
and accepts defaults for the others what to do? This seems wrong:
fnWithDefaults(10, undefined, undefined, 40);
The answer is: refactor fnWithDefaults
to accept a single object:
let fnWithDefaults = ({ a=1, b=2, c=3, d=4 }={}) => console.log(a, b, c, d);
fnWithDefaults({ a: 10, d: 40 }); // Now this looks really nice! (And never talks about "undefined")
I believe that vacuousness should never be dealt with in a generic fashion. We should instead always have the rigour to get more information about our data before determining if it is vacuous - I mainly do this by checking what type of data I'm dealing with:
let isType = (value, Cls) => {
// Intentional use of loose comparison operator detects `null`
// and `undefined`, and nothing else!
return value != null && Object.getPrototypeOf(value).constructor === Cls;
};
Note that this function ignores inheritance - it expects value
to be a direct instance of Cls
, and not an instance of a subclass of Cls
. I avoid instanceof
for two main reasons:
([] instanceof Object) === true
("An Array is an Object")('' instanceof String) === false
("A String is not a String")Note that Object.getPrototypeOf
is used to avoid an (obscure) edge-case such as let v = { constructor: String };
The isType
function still returns correctly for isType(v, String)
(false), and isType(v, Object)
(true).
Overall, I recommend using this isType
function along with these tips:
let v = JSON.parse(someRawValue);
, our v
variable is now of unknown type. As early as possible, we should limit our possibilities. The best way to do this can be by requiring a particular type: e.g. if (!isType(v, Array)) throw new Error('Expected Array');
- this is a really quick and expressive way to remove the generic nature of v
, and ensure it's always an Array
. Sometimes, though, we need to allow v
to be of multiple types. In those cases, we should create blocks of code where v
is no longer generic, as early as possible:if (isType(v, String)) {
/* v isn't generic in this block - It's a String! */
} else if (isType(v, Number)) {
/* v isn't generic in this block - It's a Number! */
} else if (isType(v, Array)) {
/* v isn't generic in this block - it's an Array! */
} else {
throw new Error('Expected String, Number, or Array');
}
if (v === null) throw new Error('Null value rejected');
- this is great for ensuring that null
values don't make it through, but if a value does make it through, we still know hardly anything about it. A value v
which passes this null-check is still VERY generic - it's anything but null
! Blacklists hardly dispell generic-ness.null
, never consider "a vacuous value". Instead, consider "an X which is vacuous". Essentially, never consider doing anything like if (isEmpty(val)) { /* ... */ }
- no matter how that isEmpty
function is implemented (I don't want to know...), it isn't meaningful! And it's way too generic! Vacuousness should only be calculated with knowledge of val
's type. Vacuousness-checks should look like this:
"A string, with no chars":
if (isType(val, String) && val.length === 0) ...
"An Object, with 0 props": if (isType(val, Object) && Object.entries(val).length === 0) ...
"A number, equal or less than zero": if (isType(val, Number) && val <= 0) ...
"An Array, with no items": if (isType(val, Array) && val.length === 0) ...
The only exception is when null
is used to signify certain functionality. In this case it's meaningful to say: "A vacuous value": if (val === null) ...
Upvotes: 22
Reputation: 6496
Check for undefined and null ONLY using "nullish coalescing"
if ((myVariable ?? undefined) !== undefined) {
// handle myVariable has a value, including 0 or ""
}
else {
// handle undefined or null only
}
from chrome console
{const x=undefined; (x ?? undefined) !== undefined}
false
{const x=null; (x ?? undefined) !== undefined}
false
{const x=0; (x ?? undefined) !== undefined}
true
{const x=""; (x ?? undefined) !== undefined}
true
{const x={}; (x ?? undefined) !== undefined}
true
{const x=[]; (x ?? undefined) !== undefined}
true
{const x="a"; (x ?? undefined) !== undefined}
true
Upvotes: 2
Reputation: 89
you can always use loadash functions, like _.isNil or _.isUndefined. They are pretty easy to use.
Upvotes: -4
Reputation: 2939
I think this makes your code looks simpler
To check if variable IS undefined
or null
var a=undefined, b=null, c='hello world', d;
if(a !== (a ?? {})) { /**/ } // true
if(b !== (b ?? {})) { /**/ } // true
if(c !== (c ?? {})) { /**/ } // false
if(d !== (d ?? {})) { /**/ } // true
To check if variable is NOT undefined
or null
var a=undefined, b=null, c='hello world', d;
if(a === (a ?? {})) { /**/ } // false
if(b === (b ?? {})) { /**/ } // false
if(c === (c ?? {})) { /**/ } // true
if(d === (d ?? {})) { /**/ } // false
Upvotes: 1
Reputation: 49182
this is my solution to check if data is empty or not.
const _isEmpty = (data) => {
return (
// this way we can also check for undefined values. null==undefined is true
data == null ||
data == "" ||
(Array.isArray(data) && data.length === 0) ||
// we want {} to be false. we cannot use !! because !!{} turns to be true
// !!{}=true and !!{name:"yilmaz"}=true. !! does not work ofr objects
(data.constructor === Object && Object.keys(data).length === 0)
);
};
Upvotes: 2
Reputation: 1164
You could use the nullish coalescing operator ??
to check for null
and undefined
values. See the MDN Docs
null ?? 'default string'; // returns "default string"
0 ?? 42; // returns 0
(null || undefined) ?? "foo"; // returns "foo"
Upvotes: 7
Reputation: 582
Will return false
only for undefined
and null
:
return value ?? false
Upvotes: 2
Reputation:
function validateAttrs(arg1, arg2, arg3,arg4){
var args = Object.values(arguments);
return (args.filter(x=> x===null || !x)).length<=0
}
console.log(validateAttrs('1',2, 3, 4));
console.log(validateAttrs('1',2, 3, null));
console.log(validateAttrs('1',undefined, 3, 4));
console.log(validateAttrs('1',2, '', 4));
console.log(validateAttrs('1',2, 3, null));
Upvotes: -1
Reputation: 382
Try Boolean() and isNaN() (for number type) to check a variable has a value or not.
function isEmpty(val) {
return typeof val === 'number' ? isNaN(val) : !Boolean(val);
}
var emptyVals = [undefined, null, false, NaN, ''];
emptyVals.forEach(v => console.log(isEmpty(v)));
Upvotes: 1
Reputation: 2724
function notEmpty(value){
return (typeof value !== 'undefined' && value.trim().length);
}
it will also check white spaces (' ') along with following:
Upvotes: 2
Reputation: 92347
The probably shortest answer is
val==null || val==''
if you change rigth side to val===''
then empty array will give false. Proof
function isEmpty(val){
return val==null || val==''
}
// ------------
// TEST
// ------------
var log = (name,val) => console.log(`${name} -> ${isEmpty(val)}`);
log('null', null);
log('undefined', undefined);
log('NaN', NaN);
log('""', "");
log('{}', {});
log('[]', []);
log('[1]', [1]);
log('[0]', [0]);
log('[[]]', [[]]);
log('true', true);
log('false', false);
log('"true"', "true");
log('"false"', "false");
log('Infinity', Infinity);
log('-Infinity', -Infinity);
log('1', 1);
log('0', 0);
log('-1', -1);
log('"1"', "1");
log('"0"', "0");
log('"-1"', "-1");
// "void 0" case
console.log('---\n"true" is:', true);
console.log('"void 0" is:', void 0);
log(void 0,void 0); // "void 0" is "undefined" - so we should get here TRUE
More details about ==
(source here)
BONUS: Reason why ===
is more clear than ==
To write clear and easy understandable code, use explicite list of accepted values
val===undefined || val===null || val===''|| (Array.isArray(val) && val.length===0)
function isEmpty(val){
return val===undefined || val===null || val==='' || (Array.isArray(val) && val.length===0)
}
// ------------
// TEST
// ------------
var log = (name,val) => console.log(`${name} -> ${isEmpty(val)}`);
log('null', null);
log('undefined', undefined);
log('NaN', NaN);
log('""', "");
log('{}', {});
log('[]', []);
log('[1]', [1]);
log('[0]', [0]);
log('[[]]', [[]]);
log('true', true);
log('false', false);
log('"true"', "true");
log('"false"', "false");
log('Infinity', Infinity);
log('-Infinity', -Infinity);
log('1', 1);
log('0', 0);
log('-1', -1);
log('"1"', "1");
log('"0"', "0");
log('"-1"', "-1");
// "void 0" case
console.log('---\n"true" is:', true);
console.log('"void 0" is:', void 0);
log(void 0,void 0); // "void 0" is "undefined" - so we should get here TRUE
Upvotes: 14
Reputation: 2692
Below worked for me. Please do a slight change to make this fast
function isEmpty(obj) {
if (!obj) return true;
if (typeof obj == 'number') return false;
else if (typeof obj == 'string') return obj.length == 0;
else if (Array.isArray(obj)) return obj.length == 0;
else if (typeof obj == 'object') return obj == null || Object.keys(obj).length == 0;
else if (typeof obj == 'boolean') return false;
}
Upvotes: 0
Reputation: 1180
The optional chaining operator provides a way to simplify accessing values through connected objects when it's possible that a reference or function may be undefined or null.
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls" // detailed address is unknown
}
};
let customerCity = customer.details?.address?.city;
The nullish coalescing operator may be used after optional chaining in order to build a default value when none was found:
let customer = {
name: "Carl",
details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
Upvotes: 4
Reputation: 3185
Most of the existing answers failed for my use case, most returned empty if a function was assigned to the variable or if NaN was returned. Pascal's answer was good.
Here's my implementation, please test and let me know if you find anything. You can see how I tested this function here.
function isEmpty(value) {
return (
// Null or undefined.
(value == null) ||
// Check if a Set() or Map() is empty
(value.size === 0) ||
// NaN - The only JavaScript value that is unequal to itself.
(value !== value) ||
// Length is zero && it's not a function.
(value.length === 0 && typeof value !== "function") ||
// Is an Object && has no keys.
(value.constructor === Object && Object.keys(value).length === 0)
)
}
Returns:
undefined
, null
, ""
, []
, {}
, NaN
, new Set()
, //
true
, false
, 1
, 0
, -1
, "foo"
, [1, 2, 3]
, { foo: 1 }
, function () {}
Upvotes: 1
Reputation: 2521
const isEmpty = value => (
(!value && value !== 0 && value !== false)
|| (Array.isArray(value) && value.length === 0)
|| (isObject(value) && Object.keys(value).length === 0)
|| (typeof value.size === 'number' && value.size === 0)
// `WeekMap.length` is supposed to exist!?
|| (typeof value.length === 'number'
&& typeof value !== 'function' && value.length === 0)
);
// Source: https://levelup.gitconnected.com/javascript-check-if-a-variable-is-an-object-and-nothing-else-not-an-array-a-set-etc-a3987ea08fd7
const isObject = value =>
Object.prototype.toString.call(value) === '[object Object]';
Poor man's tests 😁
const test = () => {
const run = (label, values, expected) => {
const length = values.length;
console.group(`${label} (${length} tests)`);
values.map((v, i) => {
console.assert(isEmpty(v) === expected, `${i}: ${v}`);
});
console.groupEnd();
};
const empty = [
null, undefined, NaN, '', {}, [],
new Set(), new Set([]), new Map(), new Map([]),
];
const notEmpty = [
' ', 'a', 0, 1, -1, false, true, {a: 1}, [0],
new Set([0]), new Map([['a', 1]]),
new WeakMap().set({}, 1),
new Date(), /a/, new RegExp(), () => {},
];
const shouldBeEmpty = [
{undefined: undefined}, new Map([[]]),
];
run('EMPTY', empty, true);
run('NOT EMPTY', notEmpty, false);
run('SHOULD BE EMPTY', shouldBeEmpty, true);
};
Test results:
EMPTY (10 tests)
NOT EMPTY (16 tests)
SHOULD BE EMPTY (2 tests)
Assertion failed: 0: [object Object]
Assertion failed: 1: [object Map]
Upvotes: 3
Reputation: 5313
Take a look at the new ECMAScript Nullish coalescing operator
You can think of this feature - the ??
operator - as a way to “fall back” to a default value when dealing with null
or undefined
.
let x = foo ?? bar();
Again, the above code is equivalent to the following.
let x = (foo !== null && foo !== undefined) ? foo : bar();
Upvotes: 37
Reputation: 3860
This covers empty Array and empty Object also
null, undefined, ' ', 0, [ ], { }
isEmpty = (value) => (!value || (typeof v === 'object' &&
Object.keys(value).length < 1));
Upvotes: -1
Reputation: 5260
This is the safest check and I haven't seen it posted here exactly like that:
if (typeof value !== 'undefined' && value) {
//deal with value'
};
It will cover cases where value was never defined, and also any of these:
Edited: Changed to strict equality (!==) because it's the norm by now ;)
Upvotes: 74
Reputation: 149
Try With Different Logic. You can use bellow code for check all four(4) condition for validation like not null, not blank, not undefined and not zero only use this code (!(!(variable))) in javascript and jquery.
function myFunction() {
var data; //The Values can be like as null, blank, undefined, zero you can test
if(!(!(data)))
{
alert("data "+data);
}
else
{
alert("data is "+data);
}
}
Upvotes: 5
Reputation: 2868
If you want to avoid getting true if the value is any of the following, according to jAndy's answer:
One possible solution that might avoid getting truthy values is the following:
function isUsable(valueToCheck) {
if (valueToCheck === 0 || // Avoid returning false if the value is 0.
valueToCheck === '' || // Avoid returning false if the value is an empty string.
valueToCheck === false || // Avoid returning false if the value is false.
valueToCheck) // Returns true if it isn't null, undefined, or NaN.
{
return true;
} else {
return false;
}
}
It would be used as follows:
if (isUsable(x)) {
// It is usable!
}
// Make sure to avoid placing the logical NOT operator before the parameter (isUsable(!x)) and instead, use it before the function, to check the returned value.
if (!isUsable(x)) {
// It is NOT usable!
}
In addition to those scenarios, you may want to return false if the object or array is empty:
You would go about it this way:
function isEmptyObject(valueToCheck) {
if(typeof valueToCheck === 'object' && !Object.keys(valueToCheck).length){
// Object is empty!
return true;
} else {
// Object is not empty!
return false;
}
}
function isEmptyArray(valueToCheck) {
if(Array.isArray(valueToCheck) && !valueToCheck.length) {
// Array is empty!
return true;
} else {
// Array is not empty!
return false;
}
}
If you wish to check for all whitespace strings (" "), you may do the following:
function isAllWhitespace(){
if (valueToCheck.match(/^ *$/) !== null) {
// Is all whitespaces!
return true;
} else {
// Is not all whitespaces!
return false;
}
}
Note: hasOwnProperty
returns true for empty strings, 0, false, NaN, null, and undefined, if the variable was declared as any of them, so it might not be the best to use. The function may be modified to use it to show that it was declared, but is not usable.
Upvotes: 5
Reputation: 1181
A solution I like a lot:
Let's define that a blank variable is null
, or undefined
, or if it has length, it is zero, or if it is an object, it has no keys:
function isEmpty (value) {
return (
// null or undefined
(value == null) ||
// has length and it's zero
(value.hasOwnProperty('length') && value.length === 0) ||
// is an Object and has no keys
(value.constructor === Object && Object.keys(value).length === 0)
)
}
Returns:
undefined
, null
, ""
, []
, {}
true
, false
, 1
, 0
, -1
, "foo"
, [1, 2, 3]
, { foo: 1 }
Upvotes: 35
Reputation: 1826
It may be usefull.
All values in array represent what you want to be (null, undefined or another things) and you search what you want in it.
var variablesWhatILookFor = [null, undefined, ''];
variablesWhatILookFor.indexOf(document.DocumentNumberLabel) > -1
Upvotes: 6
Reputation: 6468
! check for empty strings (""), null, undefined, false and the number 0 and NaN. Say, if a string is empty var name = ""
then console.log(!name)
returns true
.
function isEmpty(val){
return !val;
}
this function will return true if val is empty, null, undefined, false, the number 0 or NaN.
OR
According to your problem domain you can just use like !val
or !!val
.
Upvotes: 21
Reputation: 1301
return val || 'Handle empty variable'
is a really nice and clean way to handle it in a lot of places, can also be used to assign variables
const res = val || 'default value'
Upvotes: 8
Reputation: 636
function isEmpty(obj) {
if (typeof obj == 'number') return false;
else if (typeof obj == 'string') return obj.length == 0;
else if (Array.isArray(obj)) return obj.length == 0;
else if (typeof obj == 'object') return obj == null || Object.keys(obj).length == 0;
else if (typeof obj == 'boolean') return false;
else return !obj;
}
In ES6 with trim to handle whitespace strings:
const isEmpty = value => {
if (typeof value === 'number') return false
else if (typeof value === 'string') return value.trim().length === 0
else if (Array.isArray(value)) return value.length === 0
else if (typeof value === 'object') return value == null || Object.keys(value).length === 0
else if (typeof value === 'boolean') return false
else return !value
}
Upvotes: 6
Reputation: 10604
If you are using TypeScript
and don't want to account for "values those are false
" then this is the solution for you:
First: import { isNullOrUndefined } from 'util';
Then: isNullOrUndefined(this.yourVariableName)
Please Note: As mentioned below this is now deprecated, use value === undefined || value === null
instead. ref.
Upvotes: 5
Reputation: 1241
try{
let vari = obj.propTest; // obj may be don't have propTest property
...
} catch(NullException){
// do something here
}
I think using try catch will avoid any error of null check, also in Angular or JavaScript Just catching null exception and process in it.
Upvotes: 0