176

I'm looking for a method for JavaScript that returns true or false when it's empty... something like Ruby any? or empty?

[].any? #=> false
[].empty? #=> true
Oriol Roma
  • 329
  • 1
  • 5
  • 9
kangkyu
  • 5,252
  • 3
  • 34
  • 36

13 Answers13

205

The JavaScript native .some() method does exactly what you're looking for:

function isBiggerThan10(element, index, array) {
  return element > 10;
}

[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Alex Antonov
  • 14,134
  • 7
  • 65
  • 142
  • 1
    Thank you, I see now `[12,5,8,1,4].some(function(e){ return e > 10;});` working! – kangkyu Jan 05 '16 at 10:01
  • 5
    @kangkyu I think it's time to accept this answer ;) – Alex Antonov Aug 05 '16 at 13:23
  • 4
    Sorry for late response, but @asiniy I still think the accepted answer should have been accepted because it has more details (including `some()`) and can be more helpful to others. – kangkyu Nov 03 '16 at 17:36
  • @kangkyu I respectfully disagree. As someone who's used this question to double check on the mechanics of some, the accepted answer, I find, is pretty tursely written, it takes a few reads for me to get my brain around it. Perhaps I'm exceptionally dull witted today, or maybe this answer is just written in an easier to comprahend fashion – Craig Brett Nov 21 '17 at 15:16
  • 9
    @kangkyu Except the currently accepted answer spends more time trying to be Ruby-ish than actually giving a javascript answer. It also recommends writing your own wrapper (which *really* isn't necessary) and does so in a potentially harmful way (i.e. extending the prototype for something that isn't a polyfill) – Jasper Oct 12 '18 at 08:33
  • 1
    @Jasper, the accepted answer *is* giving a javascript answer (it might also happen to be ruby-ish). It also implements what javascript has failed to do - `[].any()` returns `false`, while `[].some()` fails. – Loki Kriasus Aug 04 '19 at 23:32
  • 2
    @LokiKriasus Extending the prototype may cause future problems (i.e. if in the future javascript defines a `any()` method, and someone uses it, that code may fail in weird ways when used together with a library that uses this code because you defined it slightly differently) and creates code that is harder to read for other (javascript) developers. And the whole reason for that approach is that a Ruby developer refused to learn that they should write `some()` instead of `any()` and that they shouldn't forget to pass a function to it even if the array is empty... – Jasper Aug 05 '19 at 08:06
  • @Jasper, "refused to learn" is an assumption. (I learned and made a conscious decision to add and use `any()`.) One could argue that when there's a flaw in design of tools being used it is perfectly fine to fix them. I agree that extending the prototype can be a problem (if overused, if done in unexpected ways, if does not fail if function being added is already defined, ...). As can be almost anything else (I suppose you don't refuse declaring functions because their names can collide with something in the future?). *continued...* – Loki Kriasus Aug 06 '19 at 08:17
  • *... continued* One could also argue that ES 5.1 added `some()` and a bunch of other collection-manipulating functions precisely because people were extending prototypes of built-in objects often enough. Should they not have done it when something needed is not there? Finally, I would be extremely happy if a future standard added something that collides with a custom extension of mine - that means I no longer need that extension. – Loki Kriasus Aug 06 '19 at 08:18
  • 1
    @LokiKriasus: You shouldn't be happy. Your prototype-extending code could cause unwelcome surprises for any future (years later) developer that happens to work on the same codebase. If you're only writing code for yourself and nobody else will ever work with it, go ahead. Here's a [random example](https://stackoverflow.com/a/51633865/405015) that comes to mind. – thirtydot Aug 06 '19 at 09:39
  • Also, extending the prototype *is* abuse, unless it's a polyfill. `some()` and other functions were added because people were looking for the functionality and these functions are generic enough to add to the standard. Whether people were modifying the prototype, using plain old functions or using methods on some helper object had nothing to do with it. – Jasper Aug 06 '19 at 10:14
  • @Jasper, another assumption, "refused to learn to use" != "made a conscious decision" (which is understanding benefits and drawbacks, and considering benefits to overweigh drawbacks). The standard still misses a lot of useful functionality. What are you going to do - struggle with verbose and hardly discoverable functions and hacks here and there, which lead to all kinds of bugs (thinly spread across the whole codebase and summarily more impacting than built-in object prototype conflicts - this is subjective, though), or thoughtfully extend the language? – Loki Kriasus Aug 06 '19 at 11:07
  • 1
    @Jasper, I think this discussion can be summarized by the following question and two answers, representing each viewpoint. *`Q:` Where do we draw the line with regards to built-in object prototype extensions. `A1 (your point)`: Extending for polyfills is ok. Everything else - no. `A2 (my point)`: Carefully extending for generic functionality that is missing from the standard and polyfills.* Did I get it right? If so, I think we have reached the point of irreconcilable opinions and only life can change them (: – Loki Kriasus Aug 06 '19 at 11:07
  • 1
    @LokiKriasus: There's no way to do it carefully. Let's say you unconditionally create `Array.prototype.any`. Your code is happy. Now pretend browsers add a native `Array.any` method, years later. Any developer working on your page is now subjected to your `Array.any` implementation from years ago. A debugging nightmare. Let's say instead, you check for the existence of a native `Array.any` before extending with your code. If browsers then add a native `Array.any`, *your old code* can break if there's any difference between the new native version and your years old version. See the problem? – thirtydot Aug 06 '19 at 13:36
  • 1
    @thirtydot, I believe there is a way to do it carefully. When a conflict is detected, there would be a warning message explaining what happened. – Loki Kriasus Aug 06 '19 at 15:21
  • @LokiKriasus: This conversation is no longer productive. I'm going to leave you with a [couple](https://humanwhocodes.com/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/) of [links](https://softwareengineering.stackexchange.com/questions/287827/whats-wrong-about-extending-a-class-with-prototype-methods/287853#287853), have fun. – thirtydot Aug 06 '19 at 22:16
109

JavaScript has the Array.prototype.some() method:

[1, 2, 3].some((num) => num % 2 === 0);  

returns true because there's (at least) one even number in the array.

In general, the Array class in JavaScript's standard library is quite poor compared to Ruby's Enumerable. There's no isEmpty method and .some() requires that you pass in a function or you'll get an undefined is not a function error. You can define your own .isEmpty() as well as a .any() that is closer to Ruby's like this:

Array.prototype.isEmpty = function() {
    return this.length === 0;
}

Array.prototype.any = function(func) {
   return this.some(func || function(x) { return x });
}

Libraries like underscore.js and lodash provide helper methods like these, if you're used to Ruby's collection methods, it might make sense to include them in your project.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
georg
  • 211,518
  • 52
  • 313
  • 390
40

I'm a little late to the party, but...

[].some(x => !!x)
Dudo
  • 4,002
  • 8
  • 32
  • 57
  • 5
    I guess this doesn't play well with `[false, 0, '', null, undefined]` – Brook Jordan Sep 25 '19 at 10:31
  • It works wonderfully, @BrookJordan. It returns false. The zero in there is questionable, but for the rest, I believe that is the functionality OP was after. Looking for "truthy" entities. – Dudo Apr 18 '20 at 20:55
  • Ah ok, I think I misunderstood empty. When I read empty I think of `[,,,]`. I guess the `!!` isn’t even required really then. – Brook Jordan Apr 20 '20 at 13:03
  • 3
    another, arguably more beautiful way of writing this: `[].some(x => Boolean)` – phil294 Aug 12 '20 at 13:00
  • 11
    @phil294 it should be `[].some(Boolean)` – Gershom Maes Sep 22 '20 at 18:40
  • 1
    `[].some(x => Boolean)` will always return `true`, so that won't work. @Gershy is correct, `[].some(Boolean)` actually does what OP asks. `some` takes a function to run on every element; `Boolean` is already a function that converts truthy and falsey values to true and false respectively. So by passing `Boolean`, `some` checks every element for truthy/falsey, and handles `null`, `undefined`, and `empty-string`. – flareartist Jun 11 '21 at 17:39
14
var a = [];
a.length > 0

I would just check the length. You could potentially wrap it in a helper method if you like.

TGH
  • 38,769
  • 12
  • 102
  • 135
  • i think the problem is here if you have a big array you are counting all elements unnecessarily – sonertbnc Mar 18 '19 at 21:00
  • @Snr all major interpreters provide efficient accessors for the length of arrays: https://stackoverflow.com/questions/9592241/javascript-is-the-length-method-efficient – Nazareno Lorenzo May 19 '20 at 12:10
  • 1
    This is literally the simplest and best answer beyond all those suggesting to use `some`. KISS principle! – Neo Jan 31 '22 at 09:58
14

I believe this to be the cleanest and readable option:

var empty = [];
empty.some(x => x); //returns false
JGallardo
  • 11,074
  • 10
  • 82
  • 96
Pedro Coelho
  • 1,411
  • 3
  • 18
  • 31
12

JavaScript arrays can be "empty", in a sense, even if the length of the array is non-zero. For example:

var empty = new Array(10);
var howMany = empty.reduce(function(count, e) { return count + 1; }, 0);

The variable "howMany" will be set to 0, even though the array was initialized to have a length of 10.

Thus because many of the Array iteration functions only pay attention to elements of the array that have actually been assigned values, you can use something like this call to .some() to see if an array has anything actually in it:

var hasSome = empty.some(function(e) { return true; });

The callback passed to .some() will return true whenever it's called, so if the iteration mechanism finds an element of the array that's worthy of inspection, the result will be true.

Pointy
  • 405,095
  • 59
  • 585
  • 614
5

Just use Array.length:

var arr = [];

if (arr.length)
   console.log('not empty');
else
   console.log('empty');

See MDN

haim770
  • 48,394
  • 7
  • 105
  • 133
4

If you really want to got nuts, add a new method to the prototype:

if (!('empty' in Array.prototype)) {
  Array.prototype.empty = function () {
    return this.length === 0;
  };
}

[1, 2].empty() // false
[].empty() // true

DEMO

georg
  • 211,518
  • 52
  • 313
  • 390
Andy
  • 61,948
  • 13
  • 68
  • 95
  • Thank you for help. I found [here](http://stackoverflow.com/a/7924304/3622415) for Array.compact (I live in Ruby area) and they say !!(anything truthy) returns true, so it could be something like !!array.filter(function(e){ return e }).length ? – kangkyu Feb 07 '15 at 01:34
  • if (!('any?' in Array.prototype)) { Array.prototype.any? = function () {return !!this.filter(function(e){ return e }).length;};} .... I tried this didn't work urgh – kangkyu Feb 07 '15 at 01:48
  • [Why don't you use georg's?](http://stackoverflow.com/a/28350435/1377002) Also, I don't think you can have question marks in method names. – Andy Feb 07 '15 at 02:23
  • 1
    `if (!('any' in Array.prototype)) { Array.prototype.any = function () {return !!this.filter(function(e){ return e }).length;};}` this works as `Array.any()` Thank you Andy – kangkyu Feb 07 '15 at 23:14
4

What you want is .empty not .empty() to fully mimics Ruby :

     Object.defineProperty( Array.prototype, 'empty', {
           get: function ( ) { return this.length===0 }
      } );    

then

[].empty //true
[3,2,8].empty //false

For any , see my answer here

Community
  • 1
  • 1
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
3

polyfill* :

Array.prototype.any=function(){
    return (this.some)?this.some(...arguments):this.filter(...arguments).reduce((a,b)=> a || b)
};

If you want to call it as Ruby , that it means .any not .any(), use :

Object.defineProperty( Array.prototype, 'any', {
  get: function ( ) { return (this.some)?this.some(function(e){return e}):this.filter(function(e){return e}).reduce((a,b)=> a || b) }
} ); 

__

`* : https://en.wikipedia.org/wiki/Polyfill

Community
  • 1
  • 1
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
2

Array has a length property :

[].length // 0
[0].length // 1
[4, 8, 15, 16, 23, 42].length // 6
Benoit Esnard
  • 2,017
  • 2
  • 24
  • 32
0

As someone suggested in one of the comments, checking if an array contains any elements can be done with a simple use of some.

let hasItems = array.some(x => true);
let isEmpty = !array.some(x => true);
jahu
  • 5,427
  • 3
  • 37
  • 64
0

Just use ternary operator

let myArray = []
myArray && myArray.length ? console.log(true) : console.log(false)
Khaled Ayed
  • 1,121
  • 3
  • 12
  • 29