130

How to check if an object is empty?

ex:

private brand: Brand = new Brand();

I tried:

if (this.brand) {
  console.log('is empty');   
}

not working.

4
  • 2
    you want to check if brand is an empty object without properties or if it is undefined? Commented Jun 2, 2017 at 22:03
  • Maybe it's not working because your condition tests whether this.brand is NOT empty :) Either try if(!this.brand), or do console.log('is not empty') Commented Jun 2, 2017 at 22:46
  • @adiga I want to check if the properties of this object are empty. Commented Jun 2, 2017 at 22:49
  • @Unfra can you share your Brand class? Commented Jun 3, 2017 at 8:13

14 Answers 14

229

Use Object.keys(obj).length to check if it is empty.

Output : 3

Source: Object.keys()

Sign up to request clarification or add additional context in comments.

2 Comments

@Unfra can you please mark this is the right answer? Thanks!
But if you wanted to move this into a helpful function, we don't know the types of the object to safely check it
58

You can use Object.keys like this:

class Brand { }
const brand = new Brand();

if (Object.keys(brand).length === 0) {
  console.log("No properties")
}

If you want to check if the object has at least one non-null, non-undefined property:

  • Get all the values of the object in an array using Object.values()
  • Check if at least one of has value using some

const hasValues = 
    (obj) => Object.values(obj).some(v => v !== null && typeof v !== "undefined")

class Brand { }
const brand = new Brand();

if (hasValues(brand)) {
  console.log("This won't be logged")
}

brand.name = null;

if (hasValues(brand)) {
  console.log("Still no")
}

brand.name = "Nike";

if (hasValues(brand)) {
  console.log("This object has some non-null, non-undefined properties")
}

Comments

20

Here is a comparison between the 2 most popular answers, they do have slightly different implications:

let o1 = {}
console.log(JSON.stringify(o1) === '{}')
console.log(Object.keys(o1).length === 0)
// true
// true

let o2 = { p: undefined }
console.log(JSON.stringify(o2) === '{}')
console.log(Object.keys(o2).length === 0)
// true
// false

let o3 = { l: null }
console.log(JSON.stringify(o3) === '{}')
console.log(Object.keys(o3).length === 0)
// false
// false

Comments

11

You can also use lodash for checking the object

if(_.isEmpty(this.brand)){
    console.log("brand is empty")
}

3 Comments

Embedding lodash for a js-native functionality feels overkill.
@Mozgor Lodash makes code more readable, that's the main usecase of it. Whole lodash functionality can be replaced with vanilla JS if you like wasting your time :)
@DurkoMatko there is a big difference between using lodash for deep equality - which would take several lines to recode at very least - and for a basic "is empty" check. There is also a difference between embedding lodash for this same basic and native function vs using isEmpty in a project already intensively using lodash.
11

This is the fastest construct that I'm aware of, albeit it uses somewhat puzzling for...in loop that doesn't loop (in my tests it's about 2x faster than Object.keys)

export function isObjectEmpty(object: Record<string, unknown>): boolean {
  for (const property in object) {
    // if any enumerable property is found object is not empty
    return false;
  }

  return true;
}

Comments

10
Object.keys(myObject).length == 0

A Map obj can be created with empty properties and size might not work . Object might not be equal to empty or undefined

But with above code you can find whether an object is really empty or not

Comments

9
let contacts = {};
if(Object.keys(contacts).length==0){
      console.log("contacts is an Empty Object");
}else{
      console.log("contacts is Not an Empty Object");
}

Comments

5

If you want a fully type-safe answer for this, that allows you to tell tsc that an object is, or is not empty when narrowing a union type, you can create a type guard utility function using one of the above answers as suits your needs:

const isEmpty = (obj: unknown): obj is Record<never, never> => 
  typeof obj === 'object' && obj !== null && Object.keys(obj).length === 0;

This allows you to have a type that could be an object with keys or an empty object (or any other type for that matter), and tell tsc that it is (or is not) and empty object by:

  • Checking whether the passed argument is an object
  • Checking that it's not null (typeof x === 'object' returns true for null)
  • Running any other checks that suit your use cases (depending on whether you care about null or undefined values within the object) - in this case the Object.keys().length method.

You can then use this with:

const unknownType: {prop: number} | Record<never, never> =
  functionThatCouldReturnAnEmptyObjectOrNot();

// Type guard returns 'true' and 'definitelyEmpty' will be inferred as an empty object
const definitelyEmpty = isEmpty(unknownType) ? unknownType : {};

// Type guard returns 'false', reversed with the '!', and 'definitelyNotEmpty'
// will be inferred as an object of type {prop: number}
const definitelyNotEmpty = !isEmpty(unknownType) ? unknownType : {prop: 1};

// Not using a type guard, tsc will still infer 'notNarrowed' as 
// ({prop: number} | Record<never, never>), meaning that using it where an empty 
// object (or not empty object) is required will cause a warning.
const notNarrowed = Object.keys(unknownType).length === 0 ? unknownType : {};

Some other potentially useful notes:

  • Record<never, never> means an empty object ({})
  • {} as a type annotation (e.g: const empty: {} = {}) actually means 'any non-nullish value' so is only just above any in terms of type safety, and will allow most other values (const empty: {} = 3 would be valid).

Comments

2

Careful about Object.keys and Array.some solutions, in case if your object is not even initialized and worth null.

Also care that there is no key worthing undefined.

const objNotInitialized = null;

console.log(Object.keys(objNotInitialized));


You could add an extra check in that case, leading to the final soluce :

function isEmpty(obj) {
  return !obj || !Object.keys(obj).some(x => obj[x] !== void 0);
}

console.log(isEmpty({
  x: void 0,
}));

console.log(isEmpty(null));

console.log(isEmpty({
  key: 'value',
}));


If you can use Object.values :

function isEmpty(obj) {
  return !obj || !Object.values(obj).some(x => x !== void 0);
}

console.log(isEmpty({
  x: void 0,
}));

console.log(isEmpty(null));

console.log(isEmpty({
  key: 'value',
}));


const obj = {};

// Using Object.keys to loop on the object keys and count them up
if (!Object.keys(obj).length) {
  console.log('#1 obj is empty');
}

// What if a key worth undefined ?
const objWithUndefinedKey = {
  x: void 0,
};

// Using Object.keys is not enough, we have to check the value behind to remove
// undefined values
if (!Object.keys(objWithUndefinedKey).some(x => objWithUndefinedKey[x] !== void 0)) {
  console.log('#2 obj is empty');
}

// Or more elegant using Object.values
if (!Object.values(objWithUndefinedKey).some(x => x !== void 0)) {
  console.log('#3 obj is empty');
}

// Alternative is to use for ... in
let empty = true;

for (key in objWithUndefinedKey) {
  if (objWithUndefinedKey[key] !== void 0) {
    empty = false;
  }
}

if (empty) {
  console.log('#4 obj is empty');
}

Comments

1
JSON.stringify(this.brand) === '{}'

1 Comment

this is a lot slower than the Object aproach
0

The good approach is to have a short function that you can use everywhere in your app :

export const isEmpty = (obj) => {
return obj === null || undefined
    ? true
    : (() => {
            for (const prop in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, prop)) {
                    return false;
                }
            }
            return true;
        })();
};

1 Comment

return condition ? true : some_code is the same as return condition || some_code.
0

If you build ECMA 7+ can try Object.entries(obj).length === 0 && obj.constructor === Object

Comments

0

Since I'm using type-fest's EmptyObject, I went with this typeguard:

is.emptyObject(val)

https://github.com/sindresorhus/is#emptyobjectvalue

Returns true if the value is an Object and Object.keys(value).length is 0.

Please note that Object.keys returns only own enumerable properties. Hence something like this can happen:

const object1 = {};

Object.defineProperty(object1, 'property1', {
    value: 42,
    writable: true,
    enumerable: false,
    configurable: true
});

is.emptyObject(object1);
//=> true

Comments

-1

Object.values(this.brand).some(b => b != null);

1 Comment

{"foo": null} is not an empty object.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.