For any of those optimizations to happen for your WASM code, the compiler has to be able to do it statically and that can be much harder. Devirtualization in particular is essential for Java or C# to run fast and some C++ codebases also benefit tremendously from it. If you're interacting a lot with JS APIs from WASM (like issuing network requests or creating DOM elements, etc) you're going to be dealing with lots of dynamically typed data, and in those scenarios handwritten JS may actually be faster than WASM because the runtime can JIT optimal code with the right type specializations.
Note that these optimizations will fail if you aren't careful about how you write your JS: If a given function f(x,y) is passed values of different types during execution, it probably won't be fully optimized. If you have two functions f1(x,y) and f2(x,y) and ensure that each one is only passed values of a certain type, they will both be heavily optimized (iirc the JS runtime terminology for these functions is 'monomorphic') Naturally, this means uses of Function.apply and Function.call should be avoided at all costs.