← all labs  ·  next lab →

Orientation Class 1

Python vs JavaScript — First, Where Do They Fit?

Before any JavaScript syntax at all: a map of the programming-language landscape, so Python and JavaScript's similarities and differences have context instead of feeling like an arbitrary pile of rules.

What this class produces: no files, no commit — pure orientation. Two tiny runnable experiments, everything else is reading and comparing.
How to read this class: map → intuition → small experiment → precise model → later depth. Several topics below get one or two sentences and an explicit "we'll come back to this" — that's deliberate. This class is landmarks, not depth. Do not try to memorize the grids. Skim them once, then move on.

1. The 10-Minute Map of Programming Languages

"Programming language" is an enormous category. Before zooming into Python and JavaScript, it helps to see roughly where they sit among languages you may have heard of — not as a strict family tree, but as a rough map.

A rough landscape of programming languages, grouped by general character Four loose clusters: systems languages, managed/VM languages, high-level dynamic languages, and declarative/structural languages, with no strict hierarchy implied between them. closer to the machine Assembly C C++ Rust managed runtimes C# / .NET Java / Kotlin (JVM) Go high-level dynamic Python JavaScript TypeScript ↑ declarative / structural — not general-purpose in the same sense SQL Bash / Shell HTML CSS

This is a mental map, not an evolutionary tree or a strict hierarchy. Arrows and boxes here mean "loosely near," not "descended from" or "better than." A language can genuinely belong near more than one cluster — Go borrows systems-language concerns while still being garbage-collected and easy to pick up; TypeScript is JavaScript with a type layer bolted on top, not a separate ecosystem.


2. Multiple Axes, Not One Ladder

A single "advanced → beginner" or "low-level → high-level" scale can't actually place these languages correctly, because they differ along several independent questions at once. A language can score differently on each one — these are axes, not boxes.

  1. How much abstraction does it provide from the machine?
  2. Static or dynamic typing?
  3. What happens between source code and execution?
  4. Native machine code, bytecode, a VM, an interpreter, JIT compilation, or some mix?
  5. Who manages memory — the programmer, or the runtime?
  6. Does it use garbage collection?
  7. What programming paradigms does it support?
  8. What environments does it normally run in?
  9. What was it primarily designed to make easier?
  10. Where is it commonly used today?

3. Language Landscape Grid

A map, not a lesson — skim once, keep coming back to it if you want, don't memorize it.

LanguageAbstractionTypingExecution modelMemoryOriginal motivationCommon today
AssemblyLowestNone (raw)Direct machine codeManualDirect hardware controlFirmware, drivers, tight loops
CLowStaticCompiled to nativeManualPortable systems programmingOS kernels, embedded
C++Low–midStaticCompiled to nativeManual (+ RAII)Abstraction w/o giving up controlGames, engines, perf-critical apps
RustLow–midStaticCompiled to nativeOwnership/borrowing, no GCSystems control, memory safetySystems tools, WASM, infra
GoMidStaticCompiled to nativeGarbage collectedSimplicity at scaleCloud services, CLIs
C#MidStatic (+ dynamic escape hatches)Compiled to IL, JIT on .NET runtimeGarbage collectedModern managed apps on .NETEnterprise, games (Unity), web
JavaMidStaticCompiled to bytecode, JVM (often JIT)Garbage collectedPortable managed apps ("write once")Enterprise backends, Android (via Kotlin/Java)
KotlinMidStaticCompiled to JVM bytecode (or native/JS)Garbage collectedModern ergonomics on the JVMAndroid, JVM backends
SwiftMidStaticCompiled to nativeAutomatic reference countingModern, safe Apple-platform appsiOS/macOS apps
PythonHighDynamicCompiled to bytecode, run on a VM (CPython)Garbage collectedReadability, productivityScripting, data/ML, backends
JavaScriptHighDynamicParsed/interpreted + JIT-compiled by an engineGarbage collectedScripting behavior in web pagesWeb front/back end, apps, tooling
TypeScriptHighStatic (compiles away)Compiles to JavaScript, then runs as JSSame as JS (garbage collected)Type-checking tooling for JSLarge JS codebases
BashHigh (for its domain)Untyped (mostly strings)Interpreted by the shellN/AAutomating shell commandsScripts, CI/CD glue
SQLDeclarativeStatic, schema-drivenQuery planned/executed by a database engineN/ADescribing what data you want, not how to get itDatabases, analytics
HTMLDeclarativeN/A (markup)Parsed into a document treeN/ADescribing document structureEvery web page
CSSDeclarativeN/A (rules)Parsed and applied by a rendering engineN/ADescribing presentation, separate from structureEvery web page
Precision note

Loose: "JavaScript is interpreted, Python is interpreted, C# is compiled" — as if that's three separate, mutually exclusive buckets.

More precise: a JavaScript engine (V8, SpiderMonkey, JavaScriptCore, and others) typically parses your source, may interpret it initially, and JIT-compiles hot code paths to native machine code while running — several strategies used together, not one. CPython typically compiles Python source to its own bytecode first, then that bytecode runs on the CPython virtual machine. C# compiles to an intermediate language (IL) ahead of time, which the .NET runtime then JIT-compiles. None of these are purely "compiled" or purely "interpreted" in the old, simple sense — "interpreted vs. compiled" is really several related but separate questions (row 3 and row 4 in the axes list above), not one switch.


4. Same Problem, Different Engineering Choices

Every language on this second grid solves "how do I manage memory and get useful work done" — the interesting part is how differently they each choose to do it. None of these choices is objectively "best" — each is a tradeoff suited to different problems.

DimensionC++RustGoC#PythonJavaScript
TypingStaticStaticStaticStaticDynamicDynamic
MemoryManual + RAIIOwnership/borrowingGarbage collectedGarbage collectedGarbage collectedGarbage collected
Compile/runCompiled to nativeCompiled to nativeCompiled to nativeCompiled to IL, JITCompiled to bytecode, VMParsed + interpreted + JIT by an engine
RuntimeNone (thin)None (thin)Go runtime.NET runtime (CLR)CPython VMJS engine + host (browser/Node)
ConcurrencyThreads, manual syncThreads, ownership-checkedGoroutines + channelsThreads, async/await, TasksThreads (GIL-limited), async/awaitSingle-threaded + event loop, async/await
Abstraction/controlHigh abstraction, still low-level controlSystems control, safety enforced by compilerSimple, intentionally small language surfaceHigh abstraction, managedVery high abstractionVery high abstraction
Typical strengthPerformance-critical software with fine controlPerformance with memory-safety guaranteesSimple, scalable network servicesProductive, large managed applicationsFast to write, read, and iterate onThe only language that runs natively in every browser

5. Just Enough History to Explain the Differences

Engineering pressures and tradeoffs, not mythology — nobody here was "invented because X was terrible."

C grew up in close relationship with operating systems and hardware — it's still the language most OS kernels are written in.

C++ added powerful abstractions (classes, templates, RAII) on top of C while keeping substantial systems-level control.

Java popularized the managed-VM approach for portable applications — compile once, run anywhere a JVM exists.

JavaScript was created to script behavior inside web pages, on a short timeline, then grew far beyond that original browser-only environment.

C# was developed as a modern managed language built around the .NET platform.

Python was optimized heavily for readability and productivity as a general-purpose scripting/programming language.

Go was designed partly in response to complexity encountered building and maintaining large-scale software systems.

Rust was designed to give systems-level control while preventing entire classes of memory-safety bugs at compile time.

TypeScript added static type analysis and tooling on top of the existing JavaScript ecosystem, without replacing it.


6. Now Zoom In: Python vs JavaScript

We now have the map. Set most of it aside for the rest of this class — the two dots we actually care about here are Python and JavaScript. Both sit in the same rough neighborhood: high-level, dynamically typed, garbage-collected, general-purpose languages. That similarity is real, and it's exactly why the specific differences below are worth slowing down for — nothing forces two languages in the same neighborhood to make the same design choices.

Variable declaration

Syntax
Python
age = 30
JavaScript
let age = 30;

Python binds a name with plain assignment. JavaScript requires a declaration keyword (let, const, or the legacy var) — there's no bare-assignment form for a new binding.

Reassignment vs "constants"

Language semantics
Python
MAX_SIZE = 10
# no real enforcement —
# it's just a naming convention
JavaScript
const MAX_SIZE = 10;
MAX_SIZE = 20; // throws TypeError

Python has no language-enforced constant — ALL_CAPS is a human convention only. JavaScript's const is enforced by the engine: reassigning it is a runtime error. (It only locks the binding, not the value's contents — Lab 21 covers what that means for objects.)

Dynamic typing

Type system
Python
x = 5
x = "five"  # fine
JavaScript
let x = 5;
x = "five"; // fine

Both are dynamically typed — a variable is just a name currently pointing at a value, and that value's type can change over the variable's lifetime in either language. Lab 03 goes deep on this from the JavaScript side.

"No value" values

JavaScript-specific gotcha
Python
x = None
JavaScript
let x;        // undefined
let y = null; // null

Python has one deliberate "nothing" value, None. JavaScript splits this into two: undefined (the engine's own default for an unassigned variable) and null (a value you assign yourself, on purpose). Lab 04 covers this split in full, including the undeclared-name case.

Equality

JavaScript-specific gotcha
Python
1 == "1"  # False
JavaScript
1 == "1"  // true
1 === "1" // false

Python's == never silently converts between types like this. JavaScript has two equality operators: == allows type coercion before comparing, === does not. This gets its own dedicated lab later in the curriculum.

Truthiness

Language semantics
Python
if []:      # falsy
if "":      # falsy
if "0":     # truthy (non-empty str)
JavaScript
if ([]) {}   // truthy!
if ("") {}   // falsy
if ("0") {}  // truthy

Both languages coerce values to true/false in a condition, but the falsy list differs: Python treats an empty list/dict/tuple as falsy; JavaScript treats every object — including an empty array [] — as truthy. Only a specific short list of primitive values is falsy in JS.

Blocks: indentation vs braces

Syntax
Python
if age >= 18:
    print("adult")
JavaScript
if (age >= 18) {
  console.log("adult");
}

Python uses indentation itself to define a block. JavaScript uses { } — indentation is just a convention for humans and has no effect on how the code runs.

Functions as values

General programming concept
Python
def greet():
    return "hi"

say_hi = greet
print(say_hi())
JavaScript
function greet() {
  return "hi";
}

let sayHi = greet;
console.log(sayHi());

"Functions are first-class values" isn't unique to either language — both let you store a function in a variable and call it through that name. JavaScript leans on this even more heavily in everyday code (Lab 11 covers why).

Lists vs arrays

Ecosystem / naming
Python
items = [1, 2, 3]
items.append(4)
JavaScript
let items = [1, 2, 3];
items.push(4);

Both are ordered, mutable, dynamically-sized sequences — mostly a naming and method-name difference (.append vs .push) at this level. JavaScript's array is, underneath, a specialized object — a later lab covers exactly what that means for how it stores its contents.

Dictionaries vs objects

Language design choice
Python
person = {"name": "Ada"}
print(person["name"])
JavaScript
let person = { name: "Ada" };
console.log(person.name);

Python's dictionary and JavaScript's object literal solve the same "named key to value" problem. JavaScript additionally lets you write person.name with a dot, and — unlike a Python dict — every JS object also participates in the prototype chain, a JavaScript-specific mechanism a later lab covers in depth.

Exceptions

General programming concept
Python
try:
    risky()
except ValueError as e:
    print(e)
JavaScript
try {
  risky();
} catch (e) {
  console.log(e.message);
}

Structured exception handling with try/catch is a shared, general concept — the shape is nearly identical. JavaScript doesn't have typed except ValueError-style catches; you check the error's type or message manually inside one catch block. This gets its own dedicated lab later.

Modules

Environment
Python
from math_utils import add
JavaScript
import { add } from "./mathUtils.js";

Both give each file its own scope and an explicit way to share specific things across files. JavaScript's module system arrived much later in the language's life than Python's, and is layered on top of an older, less isolated "just one shared global script" model — a later lab covers that history and why it matters.

Classes and object models

JavaScript-specific gotcha
Python
class Dog:
    def __init__(self, name):
        self.name = name
JavaScript
class Dog {
  constructor(name) {
    this.name = name;
  }
}

The syntax looks almost identical. Underneath, they are not the same model: Python's class system is class-based from the ground up. JavaScript's class keyword is syntax sitting on top of a fundamentally different mechanism — prototype-based inheritance, where objects link directly to other objects. Several labs later in this curriculum are dedicated entirely to that distinction.

Precision note

Loose: "JavaScript has classes just like Python or C#."

More precise: modern JavaScript provides class syntax that reads similarly to Python's or C#'s, but JavaScript's underlying inheritance model is prototype-based, not class-based — a class in JS is a specific, convenient way of setting up a prototype chain, not a separate object system.

Async code (preview only — full topic much later)

Runtime / environment
Python
async def fetch():
    data = await get_data()
    return data
JavaScript
async function fetch() {
  let data = await getData();
  return data;
}

Both have async/await syntax, and both rely on an event loop underneath. Python's asyncio event loop is opt-in — most Python code is written without it. JavaScript's single-threaded, event-loop-driven execution is the default, unavoidable execution model for the entire language, in every environment. We'll come back to this in depth much later.

Precision note

Loose: "JavaScript does asynchronous work."

More precise: JavaScript itself runs on a single thread with one call stack. Asynchronous work — timers, network requests, file access — is actually carried out by the host environment (the browser or Node.js), not by the JavaScript engine itself. The event loop and task/microtask queues are what decide when your JavaScript callback gets to run again, once that outside work finishes. A whole block of later labs is dedicated to this mechanism specifically.


7. Tiny Experiment: Truthiness Surprise

Primary objective: confirm the truthiness difference from the grid above, directly.

// Paste this into a JavaScript console (browser or node) — do not run it yet.

if ([]) {
  console.log("truthy");
} else {
  console.log("falsy");
}

If you know Python, what would if []: do there? Predict what this JavaScript version logs, then reveal.


8. Tiny Experiment: Constants Aren't Just a Convention

Primary objective: confirm that JavaScript's const is enforced by the engine, unlike Python's naming-only convention.

// Paste this into a JavaScript console (browser or node) — do not run it yet.

const MAX_SIZE = 10;
MAX_SIZE = 20;
console.log("reached the end");

If this were Python with MAX_SIZE = 10 then MAX_SIZE = 20, both lines would run fine. Predict what happens here, then reveal.


9. Class 1 Mental Model

Python and JavaScript occupy a similar part of the programming-language landscape: both are high-level, dynamically typed, garbage-collected, general-purpose languages.

That does not mean JavaScript is "Python with braces." They make different choices about scope, objects, equality, coercion, modules, execution environments, and asynchronous programming. Those differences are what the rest of this course investigates, one small experiment at a time.

Do not memorize the grids above. The point of this class was orientation — by now you should have a rough mental location for Assembly, C, C++, Rust, Go, Java, C#, Python, JavaScript, and TypeScript. Everything from here zooms in progressively deeper into JavaScript specifically.

← All labs  ·  Class 2 — Every Language Has to Answer These Questions →