While this is undoubtedly strictly true, it seems so high-level that the same could be said of essentially any programming task, with I/O suitably modelled, and so gets awfully close to "the C language is purely functional" (http://conal.net/blog/posts/the-c-language-is-purely-functio...).
People think about compilers as being systems code but it’s the opposite. It’s the web and business code that’s a nest of state and dependencies on systems.
Compilers are just numbers in numbers out.
The multi-paradigm nature of JS, with its first-class functions, closures, static scope semantics, class-based and prototype-based inheritance fits the best to study semantics of programming languages -- and all these concepts we implement in the course.
For low-level bytecode interpreter there will be a C++ implementation.
Unfortunately besides functional programming languages (Haskell, OCaml, etc) or modern languages (such as Rust), there are few having these features, and JavaScript is no exception. Of course you can use a poor man's substitute such as the Visitor pattern, but it's quite a hassle without a direct language support.