PONYλM2Modula-2
CodeCompared
for JavaScript programmers

You already know JavaScript.Now explore other languages.

Side-by-side, interactive cheatsheets for JavaScript programmers
comparing JavaScript to other languages. Every example runs live in your browser — no setup, no installation.

▶ Start with RubyBrowse comparisons ↓Explore the language map ↗

Choose your own path by reordering languages

Ruby⚡ Works Offline⚡ Offline

The language that inspired Rails and shaped modern web development, Ruby offers a radically different model from JavaScript — pure OOP, synchronous-first, and expressive in a way that prioritizes human readability above all.

  • Blocks and iterators — a language-level feature for the callback pattern: every method can yield, and the caller controls what happens next
  • Everything is an object — integers, booleans, and nil all respond to methods; no primitive/object split, no boxing, no wrapper types
  • Symbols — immutable, internable identifiers that fill the role of string keys but are guaranteed unique and memory-efficient
  • No event loop, no async/await — Ruby runs synchronously and sequentially; concurrency is a deliberate choice, not an unavoidable default
  • Ruby on Rails — the framework that defined opinionated web development and directly shaped the conventions Node.js frameworks still follow today
GoPre-Alpha

JavaScript's flexibility, but with static types, true concurrency, and a single deployable binary. Go trades the event loop and dynamic typing for goroutines, compile-time type safety, and 10–100× faster CPU-bound throughput.

  • Goroutines — thousands of truly parallel lightweight threads at ~2 KB each; JavaScript's async/await runs on a single thread and never uses multiple CPU cores
  • Static typing with inference — the compiler catches type mismatches before runtime; no undefined is not a function errors in production
  • No null/undefined confusion — every type has a defined zero value; accessing an uninitialized variable gives a predictable 0 or "", never undefined
  • Error values instead of throw/catch — every function that can fail says so in its signature; no silent exception propagation through async call stacks
  • Single static binary — go build produces one file with no runtime to install, no node_modules, no version manager needed on the server
  • Compile times measured in seconds for large programs — no bundler, no transpiler, no sourcemaps; edit, build, run in one step
PythonBeta⚡ Works Offline⚡ Offline

The language of data and scripting, Python is where most JavaScript developers go for data science, machine learning, and serious back-end work.

  • Significant whitespace and colons instead of curly braces and semicolons
  • One None instead of both null and undefined
  • A single value-based == with no coercion — no === needed
  • List comprehensions ([x*2 for x in items]) in place of map/filter chains
  • Real keyword arguments instead of the options-object pattern
  • Classes with explicit self and an __init__ constructor, no new
DartPre-Alpha

Flutter's language meets the web's language. Dart's sound null safety, typed collections, and async-first design offer a fundamentally different approach to safety and scalability than JavaScript's dynamic flexibility.

  • Sound null safety — String can never be null; String? can. The compiler prevents null dereferences before the program runs
  • final is Dart's const — variables are immutable by default; var is mutable (opposite of JavaScript's let/const semantics)
  • Typed collections — List<int>, Map<String, double> — mixing types is caught at compile time, not discovered at runtime
  • Named parameters with required — more explicit than JavaScript's destructuring pattern and enforced by the compiler
  • Dart 3 pattern matching, records, and sealed classes bring algebraic types to a syntax that feels familiar to JavaScript developers
KotlinPre-Alpha

Kotlin is what you reach for when JavaScript's dynamism starts costing you more than it saves. Null becomes a type-checked possibility instead of a runtime landmine, data classes replace hand-rolled object literals with real equality, and when plus sealed classes give you the exhaustive branching a switch statement never enforced — all compiled ahead of time to the JVM.

  • Null safety in the type system — String can never be null and String? must be handled before use; no more TypeError: Cannot read properties of null discovered at runtime
  • Data classes generate real equality — data class Person(val name: String, val age: Int) gets working equals, hashCode, toString, and copy(); a JavaScript object literal gets none of these for free
  • Static types checked at compile time — no typeof guards or runtime shape-checking; a whole category of JavaScript bugs never reaches production
  • Extension functions — add a method to any existing class without touching its source or its prototype; safer than JavaScript's prototype patching
  • Sealed classes with exhaustive when — the compiler forces every case to be handled, something a JavaScript switch can never guarantee
  • Coroutines — suspend fun reads like sequential code and coroutineScope guarantees structured cleanup, a stronger guarantee than a bare Promise chain or dangling async call
RustPre-Alpha

JavaScript's dynamism without the runtime surprises. Rust brings static types, memory safety without a GC, and true parallelism — while keeping closures, iterators, and expressive code patterns you'll recognize.

  • No null or undefinedOption<T> makes absence explicit in the type system, eliminating an entire class of runtime errors
  • Ownership and borrowing replace garbage collection — zero-pause memory management with no runtime overhead or GC pauses
  • Result<T, E> makes every error path explicit and type-checked — no more silent throws propagating through async call stacks
  • True OS threads that share memory safely — the borrow checker prevents data races at compile time, unlike JS Worker threads that communicate only by copying
  • Pattern matching with exhaustive match — more powerful than switch, works on any type, and the compiler enforces handling every case
  • Zero-cost abstractions — closures, iterators, and generics compile to the same machine code as hand-written loops with no runtime overhead
SwiftPre-Alpha

Apple's modern language meets the web's language. Swift's type system, optionals, and protocols offer a fundamentally different approach to safety than JavaScript's dynamic flexibility.

  • let means constant in Swift — the reverse of JavaScript where let is mutable and const is fixed
  • Optionals (String?) replace null and undefined — absence is tracked in the type system, not discovered at runtime
  • Value types (structs) vs. reference types (classes): assigning a struct copies it; JavaScript has no equivalent of value semantics
  • Protocols with default implementations replace JavaScript duck typing with compile-time-verified contracts
  • Pattern matching in switch is exhaustive and far more powerful than JavaScript's — ranges, tuples, type checks, and where clauses all in one construct
TypeScriptAlpha⚡ Works Offline⚡ Offline

The JavaScript you already know, with a type system that catches whole classes of bugs before they ship. TypeScript is a strict superset — every JS file is valid TS, and you adopt it at your own pace.

  • Type annotations on existing JS syntax — string, number, boolean, plus interfaces and aliases you define yourself
  • Structural typing: a type is satisfied by shape, not ancestry — no implements declaration needed, just match the structure
  • Generics: write a function once that works safely over any type the compiler can verify — no casts, no any
  • Type narrowing: TypeScript reads your if-checks and eliminates impossible types as control flow progresses
  • Utility types like Partial, Pick, and Readonly — a whole algebra of type transformations with no runtime cost
ZigPre-Alpha

A small, explicit systems language with no hidden control flow. Zig is where a JavaScript developer goes for native speed, manual memory, and compile-time guarantees.

  • Ahead-of-time compilation to a native binary — no runtime, no GC, no event loop
  • Static sized types (u8, i32, f64) instead of one dynamic number
  • Optionals (?T) and error unions (!T) replace null/undefined and throw
  • No truthiness — conditions must be a real bool
  • Explicit allocators instead of automatic garbage collection
  • comptime runs ordinary Zig at compile time — generics with no separate macro language
JavaPre-Alpha

What a compiler asks of you, and what it gives back. Java shares JavaScript's braces and almost none of its assumptions — you declare types up front, say which errors a method can throw, and pick an implementation for every collection. In exchange you get real threads, and errors caught before the program runs.

  • Static types checked at compile time — the class of bug that surfaces at runtime in JavaScript is refused at build time
  • == compares references, so string and object comparison needs equals() — the reverse of the lesson JavaScript teaches
  • Real OS threads with genuine data races, plus virtual threads that make blocking code scale like async
  • Checked exceptions: a failure a method can produce is part of its signature, and the compiler enforces handling it
  • No truthiness — an if takes a boolean, so there is no falsy-value list to memorize
  • Records, sealed interfaces, and switch patterns give typed discriminated unions with exhaustiveness checking
PHPPre-Alpha⚡ Works Offline⚡ Offline

Everything Node taught you about not blocking, inverted. A PHP request is a fresh process that runs top to bottom, blocks whenever it likes because nobody else is in it, and then throws the whole world away. No event loop, no promises, no async coloring — and one array type that copies on assignment where every JavaScript object is a reference.

  • A process per request: state does not survive to the next one, so caches live in Redis or the database — and a leak or a crash costs one visitor, not every visitor
  • Blocking I/O is idiomatic: file_get_contents and a database query just return, so no function needs an async twin and stack traces reach the entry point
  • One array is list and dictionary at once, ordered, and copied on assignment — objects stay references exactly as in JavaScript, and that split catches everyone
  • The request is ambient in $_GET/$_POST/$_SESSION rather than an object handed to your handler
  • match, enums, readonly properties, constructor promotion, named arguments and ?-> are all here — modern PHP is not the PHP you remember
  • Strings are functions not methods, with str_replace($search, $replace, $subject) ordered one way and strpos($haystack, $needle) the other
  • Composer instead of npm: one lockfile, PSR-4 autoloading, tens of packages instead of thousands, and no node_modules
ReScriptPre-Alpha

OCaml meets JavaScript. ReScript compiles to clean JavaScript while enforcing a sound type system, algebraic data types, and exhaustive pattern matching — eliminating entire classes of bugs that JavaScript's dynamic nature permits.

  • Sound type inference — types are inferred automatically and never lie; option<string> is guaranteed to be Some("text") or None, never an accidental null
  • Variants replace JavaScript's { type: "circle" } pattern — Circle(radius) is a typed constructor the compiler exhaustively checks
  • Exhaustive switch — the compiler errors if you miss any variant case, eliminating the silent default: return undefined bugs
  • Functions are curried by default — partial application is automatic, no manual wrapper needed
  • The -> pipe operator chains operations left-to-right — composable with any function, not just methods on an object
GDScriptPre-Alpha

Godot's native scripting language, and the natural next engine for a DragonRuby developer — dynamically typed like Ruby, Python-flavored in syntax, with the game's structure living in a retained tree of nodes rather than in one tick function.

  • Immediate mode vs. a retained scene tree — DragonRuby re-emits its whole frame from args.state every tick; Godot gives you persistent nodes you mutate in _process(delta)
  • Signals are the built-in observer pattern — a node emits died and anything can subscribe, replacing the flag you would poll every tick
  • No blocks and no yield — behavior is passed as a Callable (func(x): return x * 2) and invoked with .call()
  • No exceptions at all — no raise, no rescue; failures come back as error codes or sentinel values that every caller checks
  • Optional static typing that earns its keep — var speed := 200.0 is checked when the script loads and compiles to faster bytecode, which matters at 60 frames a second
  • match is real pattern matching, destructuring arrays and dictionaries much like Ruby 4's case/in
Drag cards to reorder · your order is saved locally