How to check the depth of an object?
Solution 1
Well, here you go buddy, a function that does exactly what you need!
utils.depthOf = function(object) {
var level = 1;
for(var key in object) {
if (!object.hasOwnProperty(key)) continue;
if(typeof object[key] == 'object'){
var depth = utils.depthOf(object[key]) + 1;
level = Math.max(depth, level);
}
}
return level;
}
A lot easier than we thought it would be. The issue was how it was incremented, it shouldn't have been recursively adding, rather getting the bottom-most and adding one, then choosing the max between two siblings.
Solution 2
This old question was recently resurrected and I don't see any answers as simple as this one (to be fair, this uses techniques not available when the question was written):
const objectDepth = (o) =>
Object (o) === o ? 1 + Math .max (-1, ... Object .values(o) .map (objectDepth)) : 0
console .log (objectDepth ({foo: {bar: {baz: 'baa'}}}))
console .log (objectDepth ({abc: 'xyz'}))
This, like most answers here, will fail when the input object is cyclic. An answer that addresses that limitation would require much more sophistication.
Solution 3
Back from the dead! Throwing my solution into the mix -
function depth (t, mem = new Set)
{ if (mem.has(t))
return Infinity
else switch (mem.add(t), t?.constructor)
{ case Object:
case Array:
return 1 + Math.max
( -1
, ...Object
.values(t)
.map(_ => depth(_, mem))
)
default:
return 0
}
}
console.log(depth({a: {b: {c: "z"}}})) // 3
console.log(depth({a: "z"})) // 1
console.log(depth({})) // 0
console.log(depth("z")) // 0
console.log(depth({a: [{b: "z"}]})) // 3
const a = []
a[0] = a
console.log(depth(a)) // Infinity
Related videos on Youtube
Kavi Siegel
I'm a developer and general tinkerer/maker of awesome things. Robotics, web developer, renovation, I live for making stuff.
Updated on February 06, 2021Comments
-
Kavi Siegel over 3 years
I'm working on a permissions system with variable depth; depending on the complexity of a page, there could be more or less levels. I searched StackOverflow to find if this has been asked before, couldn't find it.
If I have this object:
{foo:{bar:{baz : 'baa'}}}
I need it to return 3, it has 3 levels to it.
With this object:
{abc: 'xyz'}
It would have to be 1.
This is what I have so far:
utils.depthOf = function(object, level){ // Returns an int of the deepest level of an object level = level || 1; var key; for(key in object){ if (!object.hasOwnProperty(key)) continue; if(typeof object[key] == 'object'){ level++; level = utils.depthOf(object[key], level); } } return level; }
The problem is it counts sister elements too. It's actually not getting depth, it's counting all members of an object.
-
Umesh Patil over 11 yearsWhat is the argument "level" in this function ?
-
Kavi Siegel over 11 yearsIt would be called by saying
utils.depthOf({})
- the second parameter is only used for recursion, which is why the second line is saying "level equals level if level isn't false, if level is false, level is one" -
Kavi Siegel over 11 yearsThat aside, this function doesn't actually work. If there are sister elements, it counts them as depth rather than "width." - I'm still working on that.
-
Umesh Patil over 11 years+2 okay :) If I want to check dom dept of html element i.e. document. How do I call this function ?
-
Kavi Siegel over 11 yearsYou'll run into a maximum call stack problem, most likely. The
document
object is really, really deep. That's literally astack_overflow
- but you would call it by justutils.depthOf(document)
-
nktssh over 8 yearsworking wrong for situation
{test: [{...}, {...}]}
-
Case over 4 yearsI know let and minify do not play friendly together.
-
zfrisch about 4 years@nktssh that's because it's not doing a thorough enough job type checking. Arrays are objects. You would want to add another expression to the conditional using
Array.isArray
-
Scott Sauyet about 4 yearsThis would give a depth of
1
for{}
, which presumably should be0
. Maybereturn values .length ? 1 + Math .max ( /* ... */) : 0
? -
DonFuchs about 4 yearsMy thought was that primitive values should have depth 0, thus
{}
depth 1 and so on, but that's just a matter of normalisation. Thing is,{}
may be empty, but is has a depth, you can put something inside. -
DonFuchs about 4 yearsAnd
{}
should have the same depth as{foo:"bar"}
-
Scott Sauyet about 4 yearsI guess it entirely depends on your notion of depth. This is a pretty old question and I don't know if the OP is still around, but my thought was that it was equivalent to the number of nodes in the longest path to a nested property.
-
Mulan over 3 yearsdoesn't get much more simple than that!
-
Mulan over 3 years"here you go buddy" talking to yourself lmao
-
Scott Sauyet over 3 yearsNice! I didn't try to do it, but simply assumed cyclic objects would be fairly difficult. This proves me entirely wrong.
-
Mulan over 3 yearsha, i don't think i would've bothered to attempt it until reading your comment about it. it ended up being easier than i thought, too :D