JIT compilers are at risk of an attack-aiding technique called " https://en.wikipedia.org/wiki/JIT_spraying ", which is a way to get around NX (data execution prevention) protections when dropping a shellcode. The idea is that you create a large number of mathematical operations involving very large constants (32-bit or even 64-bit, using all the bytes) in your JS (or other language to be JIT-compiled), and when the compiler converts them into machine code and makes the resulting page in memory writable, you have a ready-made program (or at least collection of executable gadgets) if you jump into it at an offset. That is, because you control every byte (arbitrary control over the ones in the constants; the ones in the opcodes are predictable but more restricted), you can create code that does something totally under you control, if you enter it offset from an actual instruction boundary. This is the same approach used to create ROP gadgets, but unlike ROP gadgets (which are often in other libraries, whose addresses are randomized by ASLR), with a JIT spray you can create the perfect shellcode, including a NOP sled if your exploit doesn't afford precision targeting.
Note that JIT spraying is not itself an exploit, any more than ROP is; it's a way to get from "control of the instruction pointer" to "arbitrary code execution" on a modern machine with modern exploit mitigations (like NX, ASLR, etc.). The attacker still needs an exploit - typically a memory corruption - to gain that control.
JIT spraying does have mitigations of its own. One option is "constant blinding", where the JIT randomly selects an XOR mask and, every time it would emit an operation containing a constant (or "immediate") operand, it instead XORs the constant with the mask, and emits two instructions (an XOR that undoes the step the JIT just did, and the original operation upon the unmasked operand now present in a register). However, constant blinding has a performance impact (additional ALU operations, decreased cache density, increased register usage). Other possibilities include doing something similar to ASLR on a local scale (scattering compiled machine code haphazardly, on the basis that any given spray will now be fragmented) or inserting NOPs (not necessarily the classic opcode for them, just any non-state-changing operation) between real instructions (on the basis that this will break non-aligned instruction streams). Obviously these also have performance impact. Of course, none of these mitigations cost nearly as much performance as turning JIT compilation off entirely...
Another security risk with JIT compilers is that it increases attack surface. Compilers have bugs sometimes, like any complicated piece of software, and a known compiler bug can sometimes be used to generate illegal (per the language spec) operations such as writing to addresses that aren't supposed to be under user control (e.g. directly setting the address or length of an array's backing buffer). Interpreters also have tons of attack surface, but usually can't be turned off (even with JIT enabled, some code gets passed to the interpreter) so disabling JIT is still a reduction in total attack surface.
Finally, some attacks require the malicious code to be "close to the metal" in a way that interpreters don't really support, but compilers (including JIT) do. For example, consider the (original) Spectre CPU bug of four years back. Exploiting Spectre required executing in very small windows of time (performing a memory lookup before the speculative execution branch was terminated), using very precise timing to measure the results (difference between a cache hit and a cache miss), and of course required that the target address not be evicted from the cache before being tested. This is relatively easy with compiled code, but an interpreter might well have produced so many extra steps (including slow and cache-modifying memory accesses) that it would be totally impractical to get the tight code and accurate timings needed.
Now, with all that said... the typical reason you might want to disable JIT is actually not security at all. As I said above, compilers can be buggy, and JITs are no exception. Even aside from security risks, somebody investigating a bizarre misbehavior in their code might disable the JIT to see if that was the cause. Additionally, JITs are considerably less portable than the rest of the browser (by their nature, they must be specific to every instruction set and sometimes OS), so somebody working on porting a browser to a new platform might disable the JIT by default in early releases (even after it's nominally working) due to higher-than-normal risk of bugs causing script errors.
As for what JS-based attacks are not prevented, anything in the JS runtime (which is where most security bugs are found). For example, a double-free, use-after-free, buffer overflow (due to failure to check bounds or integer overflow or so on), etc. While these bugs might manifest differently when JIT is used or not, the underlying logic bug in the runtime that causes e.g. an object to be garbage collected while still available to the code (use after free) is typically going to manifest regardless of whether the user-supplied code is compiled or not. Such vulnerabilities have been a threat to JS engines since they were introduced in the 90s.