Generate every possible single word of three letters I was asked to generate every possible single word of three letters, so I wrote this script. How good is my code? Would it be better doing it using recursion or would that be over-engineering?



const getAllPossibleThreeLetterWords = () =&gt; {
      const chars = 'abcdefghijklmnopqrstuvwxyz'
      const arr = [];
      let text = '';
      for (let i = 0; i &lt; chars.length; i++) {
            for (let x = 0; x &lt; chars.length; x++) {
                  for (let j = 0; j &lt; chars.length; j++) {
                        text += chars[i]
                        text += chars[x]
                        text += chars[j]
                        arr.push(text)
                        text = ''
                  }
            }
      }
      return arr
}
console.log(getAllPossibleThreeLetterWords());
It is very clear both what your code does and how it does it, this is a good thing. However, right now it is incredibly rigid. If requirements change more code will need to be changed than if you spent a bit more time on making it more generic (more on this later).


You can avoid doing multiple assignments to text by combining the lines with text = chars[i] + chars[x] + chars[j]. This also removes the need to reset text to the empty string after adding the word. 
The variables i, x, and j seem to be randomly chosen. Not a big deal for loops this small, but it would be fairly easy to accidentally swap the order around. You might want to consider using a, b, and c instead. 




What would you do if you were told to modify this method so that it generates 4 letter words? How about 20 letter words? Or just n letter words? While you could write a ton of for loops, it would be better to handle a more generic case. Whether you use recursion or not is entirely up to you. 

To help you decide, here is a comparison.

Recursive, handling n letters.



let flatten = arr =&gt; arr.reduce((carry, item) =&gt; carry.concat(item), [])

let getAllWords = wordLength =&gt; {
    if (typeof wordLength != 'number') throw Error('wordLength must be a number')
    if (wordLength &lt; 0) throw Error('wordLength must be greater than or equal to zero')
    if (wordLength == 0) return []

    let alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('')
    let lengthen = word =&gt; alphabet.map(letter =&gt; word + letter)
    let addLetters = words =&gt; flatten(words.map(lengthen))
    let _getAllWords = (letters, words = alphabet, current = 1) =&gt; {
        return letters == current ? words : 
            _getAllWords(letters, addLetters(words), current + 1)
    }

    return _getAllWords(wordLength)
}

console.log(getAllWords(2))




Iterative, handling n letters.



let getAllWords = wordLength =&gt; {
    if (typeof wordLength != 'number') throw Error('wordLength must be a number.')
    if (wordLength &lt; 0) throw Error('wordLength must be greater than or equal to zero.')

    let alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('')
    let words = []
    if (wordLength != 0) words = alphabet

    for (let i = 1; i &lt; wordLength; i++) {
        let temp = []
        words.forEach(word =&gt; {
            alphabet.forEach(letter =&gt; temp.push(word + letter))
        })
        words = temp
    }

    return words
}

console.log(getAllWords(2))




It really is somewhat of a matter of opinion which is more clean. I personally would likely use the recursive version with the helper functions pulled out of the function itself to improve readability.