Функции добавить параметр - глубину вложенности.
Проверяем, чем является значение, если не объект, то возвращаем как есть. Иначе собираем новый объект, в который записываем текущую глубину вложенности и свойства исходного объекта, обработав их значения функцией - делаем рекурсивный вызов с глубиной вложенности, увеличенной на единицу:
const addDepth = (val, depth = 0) =>
val instanceof Object
? Object.entries(val).reduce((acc, n) => (
acc[n[0]] = addDepth(n[1], depth + 1),
acc
), { depth })
: val;
Но вот вопрос - что если в каких-то объектах уже присутствует свойство с тем же именем, под которым записывается глубина? Как избежать коллизии имён? Можно в качестве имени свойства для глубины использовать
символ (на этот раз без reduce'а, без рекурсии, да и копия объекта не создаётся):
const depthKey = Symbol();
function addDepth(val) {
for (const stack = [ [ val, 0 ] ]; stack.length;) {
const [ n, depth ] = stack.pop();
if (n instanceof Object) {
n[depthKey] = depth;
stack.push(...Object.values(n).map(m => [ m, -~depth ]));
}
}
}