You can use tools like jscodeshift [0] to refactor code! I've previously written codemods to migrate away from a bad design decisions. The React team has also used codemods to introduce breaking changes. AST Explorer [1] is the best tool I've found for writing codemods since it gives you nearly instant feedback and allows for a good amount of exploration.
That being said, consistency of internal data structures is probably one of those areas that separates a JIT from an offline compiler. I can see the benefit of switching to a bytecode representation pretty early in that circumstance.
The majority of developers doing yet another software as a service CRUD app or your typical “dark matter developer” who will write software that will never see the light of day outside of the company they work for would never benefit from writing a compiler or interpreter.
Now if they followed other path into programming, then by all means.
What next they aren’t a “true engineer” unless they can reverse a b-tree on the whiteboard?
Which most likely will have a good class in algorithms and data structures.
So while I don't expect every engineer to actually be able to do it, I expect him/her to be able to explain how to attack the problem.
When they certify the university and then when they issue the professional titles exam.
I am well aware that US doesn't seem to value proper engineering education, and everyone is allowed to call themselves engineers.
Thankfully not every country sees it that way.
Then there is the whole point if HR is hiring actual engineers.
* You don't translate from bytecode to AST.
* In tiered JIT architectures--typical for dynamically-typed languages like JavaScript where as you point out effective types can mutate at runtime--most code is executed by an interpreter, not as compiled machine code.[1] Interpreters are more efficient when executing a bytecode than walking an AST.
* Translating an AST straight to machine code is much more difficult than translating a low-level intermediate representation, and such representations are often easy to express as simple bytecodes. Compilers like GCC and LLVM use intermediate representations: RTL and IR. Both are effectively assembly languages, and like all assembly languages trivial to express as bytecode. GCC also has GIMPLE, a higher-level intermediate representation earlier in the pipeline which expresses a generic AST. The fact that GIMPLE and RTL coexist drives home the point that you don't want to be translating tree-like representations straight to machine code.
* You don't need to take my word for this, or the word of anyone else. Every programmer should have experience writing parsers, compilers, and interpreters, regardless of whether they took a class or even went to university. By doing this most of the reasons for the way things are done will become immediately clear to you. Note that splitting strings with regular expressions does not count as parsing, not for these purposes. A good project, however, would be to write a regular expression parser, compiler, and interpreter. There are many examples to follow and you can copy their designs exactly; just don't copy+paste as actually going through the motions and understanding the complexities inherent in the implementations is how everything will become clear.
[1] How this mutation is handled and why tiered architectures are preferable is another topic entirely.