Recursion solves a problem by having a function call itself directly or indirectly on progressively smaller instances. A terminating condition returns the completed result. section 4.3.2 section 5.5.7
Recursion is especially useful when iterative code must retain and update state. It can replace loop counters and local reassignment with parameters and return expressions, supporting composable functional code. section 4.3.2
Refactoring a character-processing loop
computeCipher carries the current index and hash as defaulted parameters. When the index reaches the data length, it returns the squared hash; otherwise, it calls itself with updated state. section 4.3.2
Listing 4.7 Refactoring computeCipher as a recursive function
function computeCipher(data, i = 0, hash = 0) {
if(i >= data.length) {
return hash ** 2;
}
return computeCipher( #1
data,
i + 1,
((hash << 5) - hash + data.charCodeAt(i)) << 0
);
}
Inspect the recursive computeCipher implementation, including its base case, state parameters, and self-call. section 4.3.2
Recursive validation follows the structure of nested data:
- Enumerate the current object into an array of child elements. section 5.5.7
- Combine the current object's isValid result with each child's validate result. section 5.5.7
- Continue until every node validates, returning Validation.Success or Validation.Failure. section 5.5.7
Listing 5.23 HasValidation mixin
const HasValidation = () => ({
validate() {
return [...this] #1
.reduce((validationResult, nextItem) => #2
validationResult.flatMap(() => nextItem.validate()),
this.isValid() #3
);
}
});
Inspect the HasValidation mixin, which recursively validates an object and its iterable children through reduce and flatMap. section 5.5.7






















