logo

How to check if a JavaScript object is empty

I had the following snippet of code and wanted to log an error only if whatever the catch block receives is an actual object with actual values. Needed a solution.

try {
  const attr = await this.contract.methods.attributes(index)
	  .call(this.defaultConfig);
  const identifierText = Web3.utils.hexToUtf8(attr);
  return identifierText;
} catch (attributeNotFoundError) {
  logger.error(`Attribute not found`, attributeNotFoundError);
  return null;
}

The code calls a smart contract getter, using Web3.js, retrieves whatever the return value is, and returns its plain text representation. Unfortunately, if there is no element at the specified index the getter throws an error, which is … an empty object.

This is both useless and not interesting to me.

I don’t care if there’s nothing set at a specified index. I do want to log the event, for historical reasons, but that’s just about it. I only want to use logger.error if I actually have an error to show.

The solution (my solution)

The first thing I thought about was Object.keys. I think the best and shortest way to find if an object is empty is to look at its keys, right? No keys, no object.

Then I also remembered the newer Object.values. Could use the same approach, if it makes you feel better. I stuck with Object.keys. So here is the updated version of the code.

try {
  const attr = await this.contract.methods.attributes(index)
	  .call(this.defaultConfig);
  const identifierText = Web3.utils.hexToUtf8(attr);
  return identifierText;
} catch (attributeNotFoundException) {
  logger.info(`No attribute available at position: ${index}`);
  // THIS is the solution
  if (Object.keys(attributeNotFoundException).length > 0) {
    logger.error(
      `Error retrieving attribute at position ${index} from blockchain: %o`,
      attributeNotFoundException
    );
  }
  return null;
}

Other solutions

Also went on Google and StackOverflow to look for solutions — I usually believe my solutions to be bulletproof, but this time I decided to check 😂. Most common solution is listed below.

function isEmpty(obj) {
    for(var key in obj) {
        if(obj.hasOwnProperty(key))
            return false;
    }
    return true;
}

if (isEmpty(someObject)) {
	// do stuff
}

It gets the job done, but it looks like one too many lines of code for such a simple task. Too many moving parts.

Please don’t do this

I also saw a suggestion to add the function above as a method, on Object.prototype, so that you can call myObject.isEmpty(). Manipulating the prototype of the built-in types/objects is veeeeerrry veeeeeerrry bad.

Don’t do it!

Before you go

To be able to help more people, I have to reach more people. If you read this article and liked it, please share it with your friends and co-workers.

If there’s anything I could do for you, DM me on Twitter.

Copyright (c) 2023 Adrian Oprea. All rights reserved.