For static analysis purposes, it is not great. Particularly if it is inside conditionals. Either you eat exponential path blowup (assuming bounded recursion and context-sensitivity) and fix-point it, or collapse the whole call graph cycle starting at the recursion into a single result (which generates false positives).
This assumes a single-thread.
Concurrent javascript code, with recursion, does not even have a decidable reachability problem, which makes it very difficult to get good answers.
Suffice to say, what is easy/hard for humans to prove is not the same as computers.
You would have a much harder time getting good static analysis results from a recursive fibonacci function than an iterative one (and this is simple tail recursion)
Why avoid recursion entirely? Because it's too easy for another programmer to accidentally convert tail-call optimized recursion into full recursion. That mistake is harder to make on code written as a loop.
If we'd be worried about our ability to analyze these then we wouldn't be able to optimize away that special case to begin with.
I do find that to my imperatively trained eyes it always screams 'stack overflow' at me and then I have to remind myself that will be optimized away.
It'd be nice if environments that provide tail call optimizations could be set to fail compilation if any non-tail-call recursion is detected.
Most compilers require you tell them, specifically, that it can tail call everything, before it will do it (i'm talking more about GCC and LLVM here, which are generic compiler frameworks). It will do some tail call optimization, but only fairly basic cases, exactly because it can't analyze what will happen.
In fact, what makes you say that recursion is difficult to analyze? Inductive proofs over recursive algorithms are generally much nicer than proofs over iterative algorithms.