VLAZ и CertainPerformance уже указали, почему ваша функция не работает.
Вот альтернативный метод, который мне кажется немного проще:
const recursiveFind = (pred) => (xs) => xs .reduce (
(r, x) => r != null ? r : pred (x) ? x : recursiveFind (pred) (x.children || []) || null,
null
)
const findById = (id) => recursiveFind(x => x.id == id)
const animals = [{name: "dogs", id: 1, children: [{name: "lessie", id: 2}, {name: "bark-a-lot", id: 3}]}, {name: "cats", id: 4, children: [{name: "meows-a-lot", id: 5, children: [{ name: "meows-a-lot-in-the-morning", id: 6}]}, {name: "whisk-ass", id: 7}]}];
console .log (findById (3) (animals))
console .log (findById (4) (animals))
Мы начнем с обобщенной функции c, которая ищет объекты, вложенные таким образом, в соответствии с предоставленной им функцией предиката. Затем мы передаем ему предикат x => x.id == id
, чтобы создать функцию, которая принимает идентификатор, а затем список значений и находит первое значение с совпадающими идентификаторами в списке, или null
, если ничего не найдено.
Если вы абсолютно не используете эту функцию recursiveFind
, вы можете вставить ее в findById
следующим образом:
const findById = (id, xs) => xs .reduce (
(r, x) => r != null ? r : x.id == id ? x : findById (id, x.children || []) || null,
null
)
findById (3, animals)
Но я бы на самом деле предпочел бы go в другом направлении, и сделать это еще более обобщенно c, используя что-то вроде этого:
const recursiveFind = (pred, descend) => (xs) => xs .reduce (
(r, x) => r != null ? r : pred (x) ? x : recursiveFind (pred, descend) (descend (x) || []) || null,
null
)
const findById = (id) => recursiveFind (x => x.id == id, x => x.children)
findById (3) (animals)
Эта версия также параметризует, как мы спускаемся в дочерние узлы. В этом случае мы просто используем x => x.children
, но это легко представить, используя другие свойства или более сложный метод.
Во всех них обратите внимание, что функция обрабатывает все узлы вашей структуры вложенного массива, даже когда мы уже нашли совпадение. Если у нас есть, первая проверка (r != null
) быстро пропускается, но если производительность критична, вы можете предпочесть решение с явными короткими замыканиями, например, от CertainPerformance.