Functional / Declarative FizzBuzz
Maybe some changes


Removing the arrays needed to hold the counter, its a huge overhead just for a counter.
Avoiding excessive logic statements using (num % val) to return strings and using the empty string to add a number (see code marked /*A*/)
Putting everything into an array to join when done as you have done. It is the quickest way to build a long string in JavaScript.


Thus we end up with the following...

const fizz = num =&gt; num % 5 ? "" : "fizz";
const buzz = num =&gt; num % 3 ? "" : "buzz";
const fizzBuzz = num =&gt; fizz(num) + buzz(num);
const fizzBuzzer = (min, max) =&gt; {
    const res = [];
    do {
        const fb =  fizzBuzz(min);
        res.push(fb ? fb : min);       /*A*/
    } while (min++ &lt; max);

    return res.join("\n");
}


Personally the function fizz, buzz, fizzBuzz are just adding code without good reason and would need to be closed over to avoid polluting what ever scope it is in.

Thus the 3 function become the expression right of const fb = 

Also I am not a fan of arrow functions in an open scope so using a function declaration to ensure accessibility.

function fizzBuzzer(min, max) {
    const res = [];
    do {
        const fb =  (min % 5 ? "" : "fizz") + (min % 3 ? "" : "buzz");
        res.push(fb ? fb : min);
    } while (min++ &lt; max);

    return res.join("\n");
}


You ask


  How consistent is this code with the best practices in functional and declarative programming?


Best practice, well that is subjective, contextual and would only have comparative meaning when compared to "bad" code?

Your code is not bad, it works , it would have been worse 3 years back due to the way JS engines handled arrays, but now most optimizers recognize the pattern and make it fly.

There is a zillion ways to write any bit of code. JS programmers can still not agree on the use of semicolons and whether or not automatic semicolon insertion was a good idea or not, so how is any bit of code ever going to be best practice.


  Are there any bad practices in it that I should be aware of?


OMDG Yes there is.... Semicolons, where are they?





// Example of bad
const fizzBuzzard = (min, max) =&gt; {
    const next = n =&gt; n &lt;= max ? order[n % 15] : () =&gt; "";
    const txt = w =&gt; n =&gt; (w ? w : n + "\n") + next(++n)(n);
    const [n, b, f, fb] = [txt(), txt("buzzard\n"), txt("fizz\n"), txt("fizzBuzzard\n")];
    const order = [fb, n, n, b, n, f, b, n, n, b, f, n, b, n, n];
    return next(min)(min);
}
console.log(fizzBuzzard(1, 100));