Compile Ready
Module 1 · JavaScript Fundamentals

Compilation vs Interpretation (JIT)

Intermediate7m read2m practice9m total
JITCompilationInterpretationPerformance

Introduction

Is JavaScript compiled or interpreted? The honest answer is both. Modern engines use Just-In-Time (JIT) compilation: they interpret bytecode for fast startup and compile hot code to native machine code for speed.

Understanding this removes a common misconception and explains why benchmarks "warm up".

Why This Matters

Saying "JavaScript is interpreted" in a senior interview is a red flag. Explaining the JIT pipeline — and phenomena like warm-up and deoptimisation — shows real depth.

Theory

The classic definitions

  • Interpreter — reads and executes code line by line. Fast to start, slower to run.
  • Compiler (AOT) — translates the whole program to machine code before running. Slow to start, fast to run.

JIT: the best of both

A Just-In-Time compiler combines them:

  1. Code is parsed to an AST and compiled to bytecode, which an interpreter runs immediately (fast startup).
  2. A profiler counts how often each function runs and records the types it sees.
  3. Hot functions are recompiled to optimised machine code using those type assumptions.
  4. If an assumption is violated later (a "number" argument suddenly is a string), the engine deoptimises — throws away the optimised code and falls back to bytecode.

Consequences you can observe

  • Warm-up: the same loop gets faster after running many times as the JIT kicks in.
  • Deopt cost: type-unstable code (changing shapes/types) can be slower than stable code because it keeps deoptimising.
  • Monomorphism wins: functions that always see the same types are the easiest to optimise.

Visual Diagrams

Interpreter vs AOT vs JIT
Interpreter : source --> run line by line            (fast start, slow run)
AOT compiler: source --> machine code --> run         (slow start, fast run)
JIT (JS)    : source --> bytecode --> run             (fast start)
                         + profile hot code
                         --> optimise to machine code (fast run)
                         --> deopt if assumptions break

JIT gives fast startup and, for hot code, near-native speed.

Output Prediction

Predict the output #1

javascript
1function add(a, b) {
2 return a + b;
3}
4
5// Stable types: the JIT can optimise this well
6let total = 0;
7for (let i = 0; i < 5; i++) {
8 total = add(total, i);
9}
10console.log(total);

Interview Questions

1Is JavaScript compiled or interpreted?

Both. Modern engines use JIT compilation: source is compiled to bytecode and interpreted for fast startup, then hot functions are compiled to optimised machine code at runtime using type feedback, with deoptimisation as a safety net. Describing JS as purely interpreted is inaccurate for engines like V8.

Asked at:GoogleMicrosoftApple
2What is deoptimisation and how do I avoid triggering it?

Deoptimisation is when the engine discards optimised machine code because a runtime assumption (usually about types or object shape) was violated, falling back to slower bytecode. Avoid it by keeping functions monomorphic — pass consistent types, keep object shapes stable, and don't mix element types in hot arrays.

Quiz

1. What best describes JIT compilation?

Summary

  • Modern JavaScript uses JIT compilation — it is both interpreted and compiled.
  • Bytecode gives fast startup; hot functions are JIT-compiled to machine code.
  • The engine deoptimises when runtime type/shape assumptions are violated.
  • Type-stable, monomorphic code is the easiest for the JIT to optimise.