I am sure you have been asked this question in one of the interviews.
It looks simple at first. But the interviewer is actually checking whether you understand recursion, objects, and how JavaScript treats arrays.
So, basically, you are given a nested object, and you are expected to simplify it by removing the nesting and printing it in a non-nested format.
Here is a simple input and output:
const input = {
a: 1,
b: {
c: 2,
d: {
e: 3
}
}
};
Output:
{ a: 1,
b_c: 2,
b_d_e: 3,
}
Now, look at the solution:
function flatten(obj, prefix = "", res = {}) {
// Loop through every key in the object
for (let key in obj) {
// Skip properties coming from prototype chain
if (!obj.hasOwnProperty(key)) return;
// If prefix exists, append current key using _
// Otherwise just use the key itself
let objKey = prefix ? `({prefix}_){key}` : key;
let value = obj[key];
// If value is an object and not null,
// recursively flatten it
if (typeof value === 'object' && value !== null) {
flatten(value, objKey, res);
} else {
// If it's a primitive value, assign it directly
res[objKey] = value;
}
}
// Return the accumulated result
return res;
}
Let us test it.
const input = {
a: 1,
b: {
c: 2,
d: {
e: [1, 2]
}
}
};
console.log(flatten(input));
// {a: 1, b_c: 2, b_d_e_0: 1, b_d_e_1: 2 }
Now, observe something interesting.
It flattens the nested object correctly.
But it also destructures the array and adds indexes as keys.
Why do you think that happened?
💡
As you know, everything in JavaScript is an object. Even Arrays.
So, when we check:
typeof value === 'object'
Arrays also satisfy that condition.
That means our recursive call is going inside arrays as well, and treating indexes (0, 1) like object keys.
That is why we are getting:
b_d_e_0: 1
b_d_e_1: 2
So, how do we fix it?
Simple.
We add one more condition to ignore Arrays.
function flatten(obj, prefix = "", res = {}) {
for (let key in obj) {
// Ensure we are working only with object's own properties
if (!obj.hasOwnProperty(key)) return;
let objKey = prefix ? `({prefix}_){key}` : key;
let value = obj[key];
// Only recurse if:
// 1. value is an object
// 2. value is not null
// 3. value is NOT an array
if (
typeof value === 'object' &&
value !== null &&
!Array.isArray(value)
) {
flatten(value, objKey, res);
} else {
// Directly assign primitives and arrays
res[objKey] = value;
}
}
return res;
}
Testing Both Cases
const input1 = {
a: 1,
b: {
c: 2,
d: {
e: [1, 2]
}
}
};
const input2 = {
a: 1,
b: {
c: 2,
d: {
e: 3
}
}
};
console.log(flatten(input1));
console.log(flatten(input2));
// { a: 1, b_c: 2, b_d_e: [ 1, 2 ] }
// { a: 1, b_c: 2, b_d_e: 3 }
That is it.
A simple recursion problem. But it tests whether you truly understand:
- How objects work
- How arrays behave internally
- How recursion accumulates results
- And how small edge cases can break your logic
This is why interviewers love this question.
That’s all, folks! I hope you found this helpful. If you enjoyed this, check out more articles on my Blog, https://blog.nandan.dev/
Feel free to comment, email me at connect@nandan.dev, or connect with me on Twitter, Instagram, or GitHub. Don’t forget to subscribe to my newsletter for regular updates on JavaScript topics!