DEV Community

Cover image for Detecting Object vs Array in JavaScript by example
Hugo Di Francesco
Hugo Di Francesco

Posted on • Originally published at codewithhugo.com on

2

Detecting Object vs Array in JavaScript by example

Let’s say we want to measure the depth of we have an object with mixed nested arrays/objects like so:

const obj = {
  myKey: {
    nest: {
      doubleNested: 'value',
      nestedArray: [ { key: 'value' } ]
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

The difficulty lies in detecting whether we should treat the value as an object (dictionary) or as a list.

We should be able to do this with the following:

function maxDepth(obj, depth = 0) {
  if (typeof obj !== 'object') {
    return depth;
  }
  const [values, depthIncrease] = Array.isArray(obj)
    ? [obj, 0]
    : [Object.values(obj), 1];
  return values.length > 0
    ? Math.max(...values.map(
      value => maxDepth(value, depth + depthIncrease))
    )
    : depth;
}
Enter fullscreen mode Exit fullscreen mode
// Some of these fail even although
// the assertions hold 🙄
console.assert(maxDepth({}), 0);
console.assert(maxDepth(''), 0);
console.assert(maxDepth([ { one: 'deep' } ]), 1);
console.assert(maxDepth({ one: 'deep' }), 1);
console.assert(maxDepth({ one: [ { two: 'deep' } ] }), 2)
console.assert(maxDepth({ one: { two: 'deep' } }), 2)
Enter fullscreen mode Exit fullscreen mode

To break down object vs primitive type detection, it’s a case of typeof obj === 'object', see this quick reminder of types of things:

console.assert(typeof '', 'string');
console.assert(typeof new String(), 'string');
console.assert(typeof 1, 'number');
console.assert(typeof Infinity, 'number');
console.assert(typeof NaN, 'number');
console.assert(typeof undefined, 'undefined');

console.assert(typeof [], 'object');
console.assert(typeof null, 'object');
console.assert(typeof {}, 'object');
console.assert(typeof new Map(), 'object');
console.assert(typeof new Set(), 'object');
Enter fullscreen mode Exit fullscreen mode

Now to separate Objects vs Arrays it’s Array.isArray every day, although we could use a check on .length, there’s also the caveat of Set or Map being passed around the function:

// Console.assert flips out again
// even though the assertions hold
console.assert(Array.isArray({}), false);
console.assert(Array.isArray(new Map()), false);
console.assert(Array.isArray(new Set()), false);

console.assert(Array.isArray([]), true);
console.assert(Array.isArray(new Array()), true);
Enter fullscreen mode Exit fullscreen mode

We could also use .length > 0, although that will check for a non-empty Array, or .length != null, and that’s a great use case for !=/==, but let’s stay away from that lest someone changes it to a !==/===.

This was sent out on the Code with Hugo newsletter last Monday.
Subscribe to get the latest posts right in your inbox (before anyone else).

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (1)

Collapse
 
0x04 profile image
Oliver Kühn • Edited

Had to mention a very simple way to detect the real data class:

const is = (object, isType = null) => {
  var type = Object.prototype.toString.call(object).slice(8, -1);
  return (isType) ? type === isType : type;
}

is([1, 2, 3], 'Array') // true
is(document) // 'HTMLDocument'

Source: Using toString() to detect object class

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay