При каждом заходе в тело функции getPermutations, от входной стоки отсекается последний символ и от получившейся строки снова вызывается функция, тут мы как бы спускаемся в низ.
Условие для остановки рекурсии:
if (string.length <= 1) {
return new Set([string]);
}
Т.е. как только цепочка вызовов дойдет до того, что на вход придет пустая строка (тут мы как бы достигли дна) произойдет возврат значения - пустая строка и теперь вы начинаем подниматься вверх.
Проще на примере, если взят строку 'ABC' на вход, то рекурсия будет такой
->getPermutations('ABC')
--> getPermutations('AB')
---> getPermutations('A')
----> getPermutations('')
<---- ''
<---'A'
<--'A', 'BA', 'AB'
<-'A', 'BA', 'AB', 'CA', 'AC', 'CBA', 'BCA', 'BAC', 'CAB', 'ACB', 'ABC'