715

What's the best way to check if an array is empty or does not exist?

Something like this?

if(array.length < 1 || array == undefined){
    //empty
}
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
Daft
  • 10,277
  • 15
  • 63
  • 105
  • 20
    You can simply do this by if(array && array.length){//do stuff} it's a more compact way – Kamran Nov 10 '17 at 08:15
  • 3
    The [related question](https://stackoverflow.com/q/1961528/145173) how to ensure an array is created, which is distinct from this question, which asks how to tell if an array either doesn't exist or is empty. – Edward Brey Nov 27 '18 at 19:24
  • @EdwardBrey yes, but that doesn't help me, I don't want to create it and maybe I'm unsure how to remove the create it part from those answers... – Claudiu Creanga Mar 15 '19 at 11:49

1 Answers1

1430

You want to do the check for undefined first. If you do it the other way round, it will generate an error if the array is undefined.

if (array === undefined || array.length == 0) {
    // array does not exist or is empty
}

Update

This answer is getting a fair amount of attention, so I'd like to point out that my original answer, more than anything else, addressed the wrong order of the conditions being evaluated in the question. In this sense, it fails to address several scenarios, such as null values, other types of objects with a length property, etc. It is also not very idiomatic JavaScript.

The foolproof approach
Taking some inspiration from the comments, below is what I currently consider to be the foolproof way to check whether an array is empty or does not exist. It also takes into account that the variable might not refer to an array, but to some other type of object with a length property.

if (!Array.isArray(array) || !array.length) {
  // array does not exist, is not an array, or is empty
  // ⇒ do not attempt to process array
}

To break it down:

  1. Array.isArray(), unsurprisingly, checks whether its argument is an array. This weeds out values like null, undefined and anything else that is not an array.
    Note that this will also eliminate array-like objects, such as the arguments object and DOM NodeList objects. Depending on your situation, this might not be the behavior you're after.

  2. The array.length condition checks whether the variable's length property evaluates to a truthy value. Because the previous condition already established that we are indeed dealing with an array, more strict comparisons like array.length != 0 or array.length !== 0 are not required here.

The pragmatic approach
In a lot of cases, the above might seem like overkill. Maybe you're using a higher order language like TypeScript that does most of the type-checking for you at compile-time, or you really don't care whether the object is actually an array, or just array-like.

In those cases, I tend to go for the following, more idiomatic JavaScript:

if (!array || !array.length) {
    // array or array.length are falsy
    // ⇒ do not attempt to process array
}

Or, more frequently, its inverse:

if (array && array.length) {
    // array and array.length are truthy
    // ⇒ probably OK to process array
}

With the introduction of the optional chaining operator (Elvis operator) in ECMAScript 2020, this can be shortened even further:

if (!array?.length) {
    // array or array.length are falsy
    // ⇒ do not attempt to process array
}

Or the opposite:

if (array?.length) {
    // array and array.length are truthy
    // ⇒ probably OK to process array
}
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • 14
    An `Array` object isn't the only object that has a length property. The _"shortest"_ way to determine if a variable is defined and an array would be this: `if (typeof varName !== 'undefined' && Object.getPrototypeOf(Object(varName)) === Object.getPrototypeOf([])) { console.log('varName is an array'); }` – Elias Van Ootegem Jun 25 '14 at 08:33
  • I prefer this method since it's more explicit. – Cros Jun 25 '14 at 08:34
  • 2
    `let isArrayWithLength = Boolean(Array.isArray(array) && array.length);` – mynameistechno Dec 16 '16 at 19:06
  • I am using this util not need to check if array is undefined `function isArrayEmpty (arr){ return ((typeof arr !== "undefined") && arr.length); }` – Muhammad Usman Oct 11 '17 at 11:23
  • 11
    Use `===` to avoid ESLint warning in the array.length condition check. – kvrao127 Mar 17 '18 at 10:23
  • no need to calculate the whole length of the array (which is expensive) (though js compilers might be able to infer this expression into something more performant), `array[0]` returns `undefined` if the array is empty, otherwise you got a non empty array. Thus `!Array.isArray(array) || !array[0]` may be a faster option. – yeyo Dec 12 '18 at 05:56
  • 3
    @yeyo `Array.length` is a data property. It's not calculated every time it is accessed. – Robby Cornelissen Dec 12 '18 at 06:01
  • 12
    if `array` is empty, `!array.length` is `true`!! – leoschet Feb 13 '19 at 22:32
  • 3
    @leoschet it makes sense if you think of it as `!0` (or `! Boolean(0)`). Keeping this in mind, you can flip the boolean again using `!![].length` if you really wanted to. Recommend checking out the following in a REPL: `[].length`, `['foo'].length`, `!0`, `!1`, `!!0`, `!!1`. – J.M. Janzen Apr 11 '19 at 14:30
  • 2
    In modern JS, that could be also interesting approach `if (array?.length > 0)` – David Constantine Jun 06 '20 at 10:10
  • 4
    @RobbyCornelissen For the readers of this that use React/Type Script, I would say that it is do important to test it with the `> 0` Otherwise statement like this will evaluate in kinda not expected way (not relevant for pure js) : `{array?.length && ` – David Constantine Jun 06 '20 at 13:06
  • 1
    @DavidConstantine Can you elaborate on why React/TypeScript might expand that conditional differently? – Noumenon Nov 13 '20 at 20:26
  • 1
    The comment in the first example should be turn round: `// does not exist = undefined or array empty = length property` – Timo Jul 25 '22 at 11:18
  • expect(arrayItem).be.empty; Would be good approach – Surajit Sarkar Aug 18 '22 at 10:08