Я думаю, что заданный вопрос не очень поможет вам узнать больше о рекурсии. Довольно хорошо по определению, функция всегда будет возвращать false
(если у вас нет циклического объекта, который может непрерывно повторяться до тех пор, пока не закончится стек.)
Так что вот вариант, который, я думаю, должен помочь: вместо возвратаfalse
, мы могли бы вернуть первый вложенный объект без свойства subProperty
. Таким образом, для вашего примера объекта это должно вернуть ссылку на вложенный {level3: 'level 3'}
объект.
Поскольку наша структура данных явно рекурсивная, это хорошее место для использования рекурсивного решения. Вот одна из возможностей:
const levelWithoutSubProperty = function (obj) {
if ('subProperty' in obj) {
return levelWithoutSubProperty (obj .subProperty)
}
return obj;
}
const obj = {level1: 'level 1', subProperty: {level2: 'level 2', subProperty: {level3: 'level 3'}}}
console .log (
levelWithoutSubProperty (obj) //~> {level3: 'level 3'}
)
Вот как это работает:
levelWithoutSubProperty({level1: 'level 1', subProperty: {level2: 'level 2', subProperty: {level3: 'level 3'}}})
// `'subProperty' in obj` returns true, so call `levelWithoutSubProperty` with its subProperty:
levelWithoutSubProperty({level2: 'level 2', subProperty: {level3: 'level 3'}})
// `'subProperty' in obj` returns true, so call `levelWithoutSubProperty` with its subProperty:
levelWithoutSubProperty({level3: 'level 3'})
// `'subProperty' in obj` returns false so
return {level3: 'level 3'}
return {level3: 'level 3'}
return {level3: 'level 3'}
Прямая рекурсия (есть другие типы, но они не намного сложнее), включая функцию, вызывающую саму себяс данными, которые в некотором роде упрощены от своих собственных параметров. В какой-то момент ввод должен быть достаточно простым, чтобы вы могли вычислить результат без другого рекурсивного вызова. Это называется base case , и важно, чтобы в каждой рекурсивной функции был хотя бы один. В противном случае функция будет продолжать вызывать себя бесконечно.
Здесь наш единственный базовый случай - когда obj
не имеет свойства subProperty
, то есть когда 'subproperty' in obj
возвращает false. В этом случае мы просто возвращаем предоставленный параметр.
Рекурсивная функция также будет иметь один или несколько рекурсивных вызовов. Здесь у нас есть только один. Мы снова вызываем нашу функцию со свойством subProperty
нашего объекта: return levelWithoutSubProperty (obj .subProperty)
Есть и другие вещи, которые мы могли бы сделать с этой функцией, чтобы сделать ее более устойчивой. Вероятно, мы должны проверить, что obj
на самом деле является объектом перед использованием 'subProperty' in obj
. И я предпочитаю использовать выражения, а не такие выражения, как if
. Поэтому я, вероятно, сам написал бы это так:
const levelWithoutSubProperty = (obj) =>
typeof obj == 'object' && 'subProperty' in obj
? levelWithoutSubProperty (obj .subProperty)
: obj
Мы могли бы захотеть сделать имя свойства для тестирования динамическим, добавив его в качестве параметра:
const deepest = (propName, obj) =>
typeof obj == 'object' && propName in obj
? deepest (propName, obj [propName])
: obj
и вызвав егокак deepest ('subProperty', obj)
.
Но это ничего не меняет в основах. У нас есть один или несколько базовых случаев, которые возвращают значение напрямую, и один или несколько рекурсивных вызовов, которые снова вызывают нашу функцию с некоторыми упрощенными данными.
Вот что такое рекурсия.