SOURCE

// 思路
// 利用递归压栈出栈的顺序 每找到一个不重复字符
// 就递归找下一个可加入的字符 然后递归出栈到上一层 继续执行上一层的循环

function fn(str, arr = [], result = []) {
    // 递归出口 arr收集满了就添加到结果数组 返回上一层继续进行循环
    if (arr.length === str.length) {
        // 注意 这里要把arr转换成字符串
        // 否则arr作为闭包在整个过程中使用 最后都会清空
        result.push(arr.join(''))
        return
    }
    // 遍历str 寻找每个可加入arr的字符
    for (let i = 0; i < str.length; i++) {
        // 跳过重复字符
        if (arr.includes(str[i])) {
            continue
        }
        arr.push(str[i])
        // 填入字符 并继续递归遍历整个str 找可能的结果
        fn(str, arr, result)
        // 递归结束 出栈回来 则弹出当前arr.push进去的str[i]
        // 然后继续循环 找可能的字符
        arr.pop()
    }
    // 每一层递归结束 都向上返回result 直至最外层
    return result
}

// 验证
console.log('abc排列组合结果:' + fn('abc')) // abc,acb,bac,bca,cab,cba
console 命令行工具 X clear

                    
>
console