Test for Empty Values in Javascript

The second article in our series covering short, but sweet, functions discusses the problem of testing for empty values. The function in question is called empty(). Similar to the PHP function of the same name, it takes a variable or property and tells you if the value is empty. The definition of empty depends on the value in question.

PHP’s empty() function is annoyingly loose. For example, 0 and false will both return true, which surprises many an unwary developer! Our JavaScript function is far more precise about what kinds of data can be considered empty:

  • undefined or null
  • a zero-length string
  • an array with no members
  • an object with no enumerable properties

Booleans and numbers are never empty, irrespective of their value. Here’s the empty() function’s code:

function empty(data)
{
  if(typeof(data) == 'number' || typeof(data) == 'boolean')
  {
    return false;
  }
  if(typeof(data) == 'undefined' || data === null)
  {
    return true;
  }
  if(typeof(data.length) != 'undefined')
  {
    return data.length == 0;
  }
  var count = 0;
  for(var i in data)
  {
    if(data.hasOwnProperty(i))
    {
      count ++;
    }
  }
  return count == 0;
}

How The Function Works

You can see there are four conditions used to test different data types. The first of these deals with Booleans and numbers, and always returns false. It could be argued that this condition is unnecessary, because, well, just don’t pass Booleans and numbers! But providing this flexibility means you can pass in arbitrary data. The second condition tests the value against undefined and null. This can be particularly helpful for setting defaults for optional function arguments, as shown in the following example.

function doSomething(foo, bar)
{
  if(empty(bar))
  {
    bar = 'default value';
  }
}

Although null is obviously not the same as undefined, for many intents and purposes they amount to the same thing (i.e. this piece of data does not have a wanted value). For example, if you query a web storage object using object syntax, a value that isn’t defined will be undefined, yet the getItem() method will return null.

The third condition in empty() handles anything with a length property. This will detect empty strings and arrays with no members. I did consider an extra condition that checks for strings which are empty or only whitespace. This test is shown below.

if(typeof(data.length) != 'undefined')
{
  if(/^[s]*$/.test(data.toString()))
  {
    return true;
  }
  return data.length == 0;
}

I decided not to include the previous check because it introduces an ambiguity. Whether or not a whitespace only string can be considered empty is a matter of opinion or application specific. Instead, I opted to keep the function as clear as possible (we’re not writing PHP after all).

The final condition handles objects, iterating through them and counting their enumerable members. If that count is zero, then the object is deemed empty.

Ignoring the Irrelevant

By virtue of being at the end, the final condition handles anything else that makes it through, including functions, regular expressions, elements, and documents. Functions and regular expressions will be treated as empty, because they generally have no enumerable properties. Elements and documents won’t be empty, because they have many properties.

This is an ambiguity that might be worth preventing, but at some point you must ask yourself, “is it really worth it?” Think about the kinds of data you’re likely to test. It will generally be simple variables, arrays, dictionaries, function arguments, form values, Ajax responses, attributes, and text-nodes; it’s unlikely to be a function, regular expression, or DOM subtree. The empty() function walks a fine line between precise evaluation and not wasting time testing every imaginable possibility.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Andre Dublin

    Couldn’t you also use
    if (undefined === value)
    sine undefined is a property of the global object?

  • http://www.brothercake.com/ James Edwards

    No, that’s really not a good idea, for all sorts of reasons.

    This thread on stackoverflow discusses them: http://stackoverflow.com/questions/776950/javascript-undefined-undefined

    I can’t add anything to that, except to echo the point that it’s not a good idea!

  • matey

    Looks like: “Well, take JS (node.js for example) and go write apps! And.., hmm.. don’t forget that trash out php. It’s really need to be lost!”
    It just looks like this.
    Does it really matter that difference between two absolutely incomparable languages in sense of data entity?
    But! JavaScript does not have «===» ! Any suggestions? Really needed? ;)
    ps. hello from albania

  • http://www.brothercake.com/ James Edwards

    Er, I’m sorry I don’t understand the question.

  • Priit
    empty = function( x ) {
    		// undefined, '', null, 0, empty array
    		if ( !x || 0 == x.length ) return true
    		// empty {}
    		if ('object'  == Object.prototype.toString.call(x).slice(8, -1).toLowerCase() ) {
    			for ( var n in x ) if ( x.hasOwnProperty(n) ) return false
    			return true
    		}
    		// convert to string and match single non-space character
    		return !(x+'').match(/S/)
    	}
  • http://www.brothercake.com/ James Edwards

    Interesting optimization on the object test there, no need to keeping counting once you’ve found a property. But the looseness of your first expression will generate a couple of false-positives for boolean false and integer zero, neither of which can be considered empty.

    I’m also not convinced that whitespace-only strings should be treated as empty — it would depend on the situation — so perhaps it would be better if that were an optional argument.