PONY λ M2 Modula-2

Python.CodeCompared.To/JavaScript

An interactive executable cheatsheet comparing Python and JavaScript

Python 3.13 JavaScript (ES2025)
Output & Running
Hello, World
print("Hello, World!")
console.log("Hello, World!");
console.log() is the JavaScript equivalent of Python's print() — both append a trailing newline. JavaScript statements conventionally end with a semicolon, though it is usually optional thanks to automatic semicolon insertion.
Printing multiple values
name = "Alice" age = 30 print(name, age) print(f"{name} is {age}")
const name = "Alice"; const age = 30; console.log(name, age); console.log(`${name} is ${age}`);
JavaScript template literals use backticks and ${...} for interpolation — the direct equivalent of Python f-strings. console.log() with multiple arguments separates them with spaces, just like Python's print().
Comments
# a single-line comment """ A multi-line string, often used as a block comment or docstring. """ print("done")
// a single-line comment /* A multi-line block comment. */ console.log("done");
JavaScript uses // for single-line comments and /* ... */ for block comments, whereas Python uses # and relies on triple-quoted strings for multi-line text.
Variables & Types
Declaring variables
message = "hi" count = 3 count = count + 1 print(message, count)
let message = "hi"; let count = 3; count = count + 1; console.log(message, count);
JavaScript requires a declaration keyword: let for variables you will reassign and const for those you will not. Python has no keyword — assignment both declares and binds. The idiomatic JavaScript naming convention is camelCase, not Python's snake_case.
Constants
MAX_RETRIES = 3 print(MAX_RETRIES)
const MAX_RETRIES = 3; console.log(MAX_RETRIES);
JavaScript's const actually prevents reassignment, so the constant is enforced by the language. Python has no real constants — the all-caps name is only a convention that nothing stops you from reassigning.
Dynamic typing
value = 42 print(type(value)) value = "now a string" print(type(value))
let value = 42; console.log(typeof value); value = "now a string"; console.log(typeof value);
Both languages are dynamically typed, so a variable can hold any type. JavaScript's typeof operator returns a string such as "number" or "string", where Python uses the type() built-in.
None vs. null and undefined
result = None print(result is None)
let result = null; let notAssigned; console.log(result === null, notAssigned === undefined);
Python has one empty value, None. JavaScript has two: null (an intentional absence you assign) and undefined (a variable declared but never given a value). This distinction is a frequent source of surprise for Python developers.
Multiple assignment & swapping
first, second = 1, 2 first, second = second, first print(first, second)
let [first, second] = [1, 2]; [first, second] = [second, first]; console.log(first, second);
JavaScript achieves Python's tuple-unpacking with array destructuring. The swap idiom [a, b] = [b, a] mirrors Python's a, b = b, a exactly.
Strings
String interpolation
name = "World" print(f"Hello, {name}!") print(f"2 + 2 = {2 + 2}")
const name = "World"; console.log(`Hello, ${name}!`); console.log(`2 + 2 = ${2 + 2}`);
JavaScript template literals (backtick strings) embed expressions with ${...}, just as Python f-strings embed them with {...}. Both evaluate arbitrary expressions inline.
Concatenation & repetition
greeting = "ab" + "cd" line = "-" * 5 print(greeting, line)
const greeting = "ab" + "cd"; const line = "-".repeat(5); console.log(greeting, line);
Both languages concatenate strings with +. For repetition, Python uses the * operator while JavaScript uses the String.prototype.repeat() method.
Common string methods
text = "Hello World" print(text.upper()) print(text.lower()) print(text.replace("World", "JS"))
const text = "Hello World"; console.log(text.toUpperCase()); console.log(text.toLowerCase()); console.log(text.replace("World", "JS"));
The method names differ — JavaScript uses toUpperCase() and toLowerCase() where Python uses upper() and lower() — but replace() exists in both. Note that JavaScript's replace() with a string argument replaces only the first match.
Slicing & substrings
word = "javascript" print(word[0:4]) print(word[-6:])
const word = "javascript"; console.log(word.slice(0, 4)); console.log(word.slice(-6));
JavaScript's slice() method accepts negative indices to count from the end, much like Python's slice syntax. There is no direct equivalent to Python's step argument (word[::2]) — you would filter by index instead.
Split & join
csv = "a,b,c" parts = csv.split(",") print(parts) print("-".join(parts))
const csv = "a,b,c"; const parts = csv.split(","); console.log(parts); console.log(parts.join("-"));
In JavaScript join() is a method on the array, called as parts.join("-"), whereas Python calls it on the separator string as "-".join(parts). The argument order feels inverted to a Python developer.
Multi-line strings
poem = """Roses are red Violets are blue""" print(poem)
const poem = `Roses are red Violets are blue`; console.log(poem);
JavaScript template literals (backticks) span multiple lines and preserve the newlines, serving the same purpose as Python's triple-quoted strings.
Numbers
Arithmetic & division
print(7 + 2, 7 - 2, 7 * 2) print(7 / 2) print(7 // 2) print(7 % 2)
console.log(7 + 2, 7 - 2, 7 * 2); console.log(7 / 2); console.log(Math.floor(7 / 2)); console.log(7 % 2);
JavaScript has only one number type, so / always produces a floating-point result. There is no integer-division operator like Python's //; use Math.floor(a / b) instead.
Exponentiation
print(2 ** 10)
console.log(2 ** 10);
Modern JavaScript shares Python's ** exponentiation operator. The older alternative, Math.pow(2, 10), still works but is no longer idiomatic.
Parsing & truncating
print(int("42"), float("3.14")) print(int(3.9))
console.log(parseInt("42"), parseFloat("3.14")); console.log(Math.trunc(3.9));
JavaScript uses parseInt() and parseFloat() to read numbers from strings, and Math.trunc() to drop the fractional part. Note that parseInt() stops at the first non-digit rather than raising an error the way Python's int() does.
Math functions
import math print(math.sqrt(16), math.floor(3.7), math.ceil(3.2))
console.log(Math.sqrt(16), Math.floor(3.7), Math.ceil(3.2));
JavaScript's math functions live on the global Math object and need no import, whereas Python groups them in the math module that you must import first.
Formatting numbers
amount = 1234.5 print(f"{amount:,.2f}")
const amount = 1234.5; console.log(amount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2, }));
Python's format mini-language (:,.2f) packs grouping and precision into a compact string. JavaScript reaches the same result through toLocaleString() with an options object, which is more verbose but locale-aware.
Lists & Arrays
Creating & indexing
fruits = ["apple", "banana", "cherry"] print(fruits[0], fruits[-1], len(fruits))
const fruits = ["apple", "banana", "cherry"]; console.log(fruits[0], fruits[fruits.length - 1], fruits.length);
JavaScript arrays have no negative indexing, so the last element is fruits[fruits.length - 1] rather than Python's fruits[-1]. Length is the length property, not the len() function.
Adding & removing elements
numbers = [1, 2, 3] numbers.append(4) numbers.pop() numbers.insert(0, 0) print(numbers)
const numbers = [1, 2, 3]; numbers.push(4); numbers.pop(); numbers.unshift(0); console.log(numbers);
JavaScript's push() matches Python's append(), and pop() exists in both. To prepend, JavaScript uses unshift() where Python uses insert(0, value). Note that you can mutate a const array — const only forbids reassigning the binding.
Slicing arrays
nums = [0, 1, 2, 3, 4, 5] print(nums[1:4]) print(nums[::2])
const nums = [0, 1, 2, 3, 4, 5]; console.log(nums.slice(1, 4)); console.log(nums.filter((_, index) => index % 2 === 0));
JavaScript's slice() covers Python's basic [start:end] slicing. There is no step argument, so to take every other element you filter by index instead of writing nums[::2].
Transforming with map
numbers = [1, 2, 3, 4] doubled = [number * 2 for number in numbers] print(doubled)
const numbers = [1, 2, 3, 4]; const doubled = numbers.map(number => number * 2); console.log(doubled);
Where Python reaches for a list comprehension, JavaScript chains array methods. The map() method is the idiomatic way to transform every element.
Filtering elements
numbers = list(range(10)) evens = [number for number in numbers if number % 2 == 0] print(evens)
const numbers = [...Array(10).keys()]; const evens = numbers.filter(number => number % 2 === 0); console.log(evens);
JavaScript's filter() replaces the conditional clause of a Python comprehension. Generating a range is less direct in JavaScript: [...Array(10).keys()] produces 0 through 9.
Reducing to a single value
numbers = [1, 2, 3, 4] print(sum(numbers)) from functools import reduce print(reduce(lambda total, number: total + number, numbers, 0))
const numbers = [1, 2, 3, 4]; console.log(numbers.reduce((total, number) => total + number, 0));
JavaScript has no sum() built-in, so summing a list means calling reduce() with an accumulator. Python offers both the simple sum() and the general functools.reduce().
Sorting
words = ["banana", "apple", "cherry"] print(sorted(words)) print(sorted(words, key=len))
const words = ["banana", "apple", "cherry"]; console.log([...words].sort()); console.log([...words].sort((a, b) => a.length - b.length));
JavaScript's sort() mutates the array in place and sorts as strings by default, so spreading into a new array ([...words]) avoids surprises. A comparator function replaces Python's key argument. Sorting numbers requires a comparator, or they sort lexicographically.
Spread & rest
first, *rest = [1, 2, 3, 4] print(first, rest) combined = [*[1, 2], *[3, 4]] print(combined)
const [first, ...rest] = [1, 2, 3, 4]; console.log(first, rest); const combined = [...[1, 2], ...[3, 4]]; console.log(combined);
JavaScript's spread (...) and rest (...) syntax mirrors Python's starred expressions for both unpacking and combining sequences.
Sets
a = {1, 2, 3} b = {2, 3, 4} print(sorted(a & b)) print(sorted(a | b))
const a = new Set([1, 2, 3]); const b = new Set([2, 3, 4]); console.log([...a].filter(value => b.has(value))); console.log([...new Set([...a, ...b])]);
JavaScript has a Set type, but it lacks Python's operator overloads for intersection (&) and union (|). You implement those with filter() and spread instead.
Dicts & Objects
Creating & accessing
person = {"name": "Alice", "age": 30} print(person["name"]) print(person.get("email", "n/a"))
const person = { name: "Alice", age: 30 }; console.log(person.name); console.log(person.email ?? "n/a");
JavaScript object keys are bare identifiers, not quoted strings, and you read them with dot notation (person.name). The nullish-coalescing operator ?? supplies a default, replacing Python's dict.get(key, default).
Adding & updating keys
scores = {} scores["math"] = 95 scores["math"] += 1 print(scores)
const scores = {}; scores.math = 95; scores.math += 1; console.log(scores);
Assigning to a key that does not yet exist creates it in both languages. JavaScript lets you use dot notation for string keys that are valid identifiers.
Iterating entries
person = {"name": "Alice", "age": 30} for key, value in person.items(): print(key, value)
const person = { name: "Alice", age: 30 }; for (const [key, value] of Object.entries(person)) { console.log(key, value); }
Object.entries() turns an object into an array of [key, value] pairs, which you destructure in the loop header — the JavaScript counterpart to Python's dict.items().
Keys & values
counts = {"a": 1, "b": 2} print(list(counts.keys())) print(list(counts.values()))
const counts = { a: 1, b: 2 }; console.log(Object.keys(counts)); console.log(Object.values(counts));
JavaScript exposes keys and values through the static methods Object.keys() and Object.values(), which already return arrays — no list() conversion needed as in Python.
Checking for a key
config = {"debug": True} print("debug" in config) print("verbose" in config)
const config = { debug: true }; console.log("debug" in config); console.log("verbose" in config);
The in operator tests for a key in both languages. Be careful: in JavaScript, in on an array checks indices, not values — so this idiom is specific to objects.
Merging
defaults = {"color": "red", "size": "m"} overrides = {"size": "l"} merged = {**defaults, **overrides} print(merged)
const defaults = { color: "red", size: "m" }; const overrides = { size: "l" }; const merged = { ...defaults, ...overrides }; console.log(merged);
JavaScript's object spread ({ ...a, ...b }) merges objects exactly like Python's double-star unpacking ({**a, **b}), with later keys winning.
When you need non-string keys
lookup = {(0, 0): "origin", (1, 2): "point"} print(lookup[(0, 0)])
const lookup = new Map(); lookup.set([0, 0].join(","), "origin"); lookup.set([1, 2].join(","), "point"); console.log(lookup.get([0, 0].join(",")));
Python dict keys can be any hashable value, including tuples. Plain JavaScript objects only allow string and symbol keys, so for richer keys you reach for a Map — though a Map compares object keys by identity, so here the coordinates are joined into a string.
Control Flow
if / elif / else
score = 75 if score >= 90: print("A") elif score >= 70: print("B") else: print("C")
const score = 75; if (score >= 90) { console.log("A"); } else if (score >= 70) { console.log("B"); } else { console.log("C"); }
JavaScript wraps conditions in parentheses and bodies in braces, replacing Python's colon-and-indentation structure. There is no elif keyword — JavaScript spells it else if.
Conditional expression
age = 20 status = "adult" if age >= 18 else "minor" print(status)
const age = 20; const status = age >= 18 ? "adult" : "minor"; console.log(status);
JavaScript uses the C-style ternary operator condition ? a : b, where Python uses the more English-like a if condition else b.
Truthiness
items = [] if not items: print("empty") name = "" print(bool(name))
const items = []; if (items.length === 0) { console.log("empty"); } const name = ""; console.log(Boolean(name));
This is a major trap: an empty list or dict is falsy in Python, but an empty array [] and empty object {} are both truthy in JavaScript. To test for emptiness in JavaScript you must check .length or Object.keys().length explicitly.
Equality: == vs. ===
print(1 == 1.0) print("1" == 1)
console.log(1 === 1); console.log("1" === 1); console.log("1" == 1);
JavaScript has two equality operators: === compares without type coercion, while == coerces types first (so "1" == 1 is true). Always prefer ===. Python's single == compares by value and does not coerce strings to numbers.
match vs. switch
command = "start" match command: case "start": print("starting") case "stop": print("stopping") case _: print("unknown")
const command = "start"; switch (command) { case "start": console.log("starting"); break; case "stop": console.log("stopping"); break; default: console.log("unknown"); }
JavaScript's switch predates and is weaker than Python's structural match: each case needs an explicit break or execution falls through to the next, and it cannot destructure patterns the way Python's match can.
Loops & Iteration
Counting loop
for index in range(3): print(index)
for (let index = 0; index < 3; index++) { console.log(index); }
JavaScript's classic C-style for loop with an explicit counter takes the place of Python's range(). The ++ increment operator has no Python equivalent.
Iterating a collection
for color in ["red", "green"]: print(color)
for (const color of ["red", "green"]) { console.log(color); }
JavaScript's for...of loop iterates values directly, just like Python's for x in collection. Beware for...in, which iterates keys/indices and is a common beginner mistake.
Index and value together
for index, color in enumerate(["red", "green"]): print(index, color)
["red", "green"].forEach((color, index) => { console.log(index, color); });
JavaScript's forEach() passes the element first and the index second — the reverse of Python's enumerate(), which yields the index first. You can also use for (const [index, color] of array.entries()).
while loop
count = 3 while count > 0: print(count) count -= 1
let count = 3; while (count > 0) { console.log(count); count -= 1; }
The while loop is nearly identical in both languages, aside from JavaScript's parentheses and braces.
break & continue
for number in range(10): if number == 3: continue if number == 6: break print(number)
for (let number = 0; number < 10; number++) { if (number === 3) continue; if (number === 6) break; console.log(number); }
Both break and continue behave identically in the two languages. JavaScript also supports labeled loops for breaking out of nested loops, which Python lacks.
Functions
Defining functions
def greet(name): return f"Hi, {name}" print(greet("Alice"))
function greet(name) { return `Hi, ${name}`; } console.log(greet("Alice"));
JavaScript uses the function keyword and an explicit return, much like Python's def. The body is delimited by braces rather than indentation.
Default arguments
def greet(name, greeting="Hello"): return f"{greeting}, {name}" print(greet("Bob")) print(greet("Bob", "Hi"))
function greet(name, greeting = "Hello") { return `${greeting}, ${name}`; } console.log(greet("Bob")); console.log(greet("Bob", "Hi"));
Default-parameter syntax is the same in both languages. Unlike Python, JavaScript evaluates the default expression fresh on every call, so the mutable-default-argument pitfall that bites Python developers does not exist here.
Keyword-style arguments
def make_user(name, *, role="user", active=True): return (name, role, active) print(make_user("Alice", role="admin"))
function makeUser(name, { role = "user", active = true } = {}) { return [name, role, active]; } console.log(makeUser("Alice", { role: "admin" }));
JavaScript has no true keyword arguments. The idiom is to accept a single options object and destructure it with defaults — the trailing = {} lets the caller omit the object entirely.
Variadic arguments
def total(*numbers): return sum(numbers) print(total(1, 2, 3, 4))
function total(...numbers) { return numbers.reduce((sum, number) => sum + number, 0); } console.log(total(1, 2, 3, 4));
JavaScript's rest parameter (...numbers) collects extra positional arguments into a real array — the counterpart to Python's *args, which collects them into a tuple.
Collecting named options
def describe(**attributes): return attributes print(describe(color="red", size="m"))
function describe(attributes) { return attributes; } console.log(describe({ color: "red", size: "m" }));
Python's **kwargs gathers arbitrary keyword arguments into a dict. JavaScript has no equivalent, so the established pattern is to pass and accept a single options object.
Returning multiple values
def min_max(numbers): return min(numbers), max(numbers) low, high = min_max([3, 1, 4, 1, 5]) print(low, high)
function minMax(numbers) { return [Math.min(...numbers), Math.max(...numbers)]; } const [low, high] = minMax([3, 1, 4, 1, 5]); console.log(low, high);
Python returns a tuple and unpacks it; JavaScript returns an array and destructures it. The pattern is the same, only the bracket style differs. Note that Math.min and Math.max take separate arguments, hence the spread.
Closures & Higher-Order Functions
Lambdas & arrow functions
square = lambda value: value * value print(square(5))
const square = value => value * value; console.log(square(5));
JavaScript arrow functions are far more capable than Python lambdas: they can contain multiple statements (with braces and return), whereas a Python lambda is limited to a single expression.
Closures & captured state
def make_counter(): count = 0 def increment(): nonlocal count count += 1 return count return increment counter = make_counter() print(counter(), counter())
function makeCounter() { let count = 0; return () => { count += 1; return count; }; } const counter = makeCounter(); console.log(counter(), counter());
Both languages support closures that capture surrounding variables. JavaScript reassigns the captured count freely, whereas Python requires the nonlocal keyword to rebind a variable from the enclosing scope.
Decorators vs. wrapping
def shout(func): def wrapper(name): return func(name).upper() return wrapper @shout def greet(name): return f"hi {name}" print(greet("alice"))
function shout(func) { return name => func(name).toUpperCase(); } const greet = shout(name => `hi ${name}`); console.log(greet("alice"));
Python's @decorator syntax is sugar for wrapping a function and rebinding its name. JavaScript has no built-in function decorator (the class-decorator proposal is separate), so you wrap manually with a higher-order function.
Classes & OOP
Class & constructor
class Dog: def __init__(self, name): self.name = name def speak(self): return f"{self.name} says woof" print(Dog("Rex").speak())
class Dog { constructor(name) { this.name = name; } speak() { return `${this.name} says woof`; } } console.log(new Dog("Rex").speak());
JavaScript's constructor is named constructor rather than __init__, instances are created with the new keyword, and the receiver is the implicit this rather than an explicit first self parameter.
Inheritance & overriding
class Animal: def __init__(self, name): self.name = name def describe(self): return f"{self.name} is an animal" class Cat(Animal): def describe(self): return f"{self.name} is a cat" print(Cat("Felix").describe())
class Animal { constructor(name) { this.name = name; } describe() { return `${this.name} is an animal`; } } class Cat extends Animal { describe() { return `${this.name} is a cat`; } } console.log(new Cat("Felix").describe());
JavaScript uses the extends keyword where Python lists the base class in parentheses. Method overriding works the same way in both — define a method with the same name in the subclass.
Calling the parent constructor
class Base: def __init__(self, value): self.value = value class Derived(Base): def __init__(self, value): super().__init__(value) self.doubled = value * 2 obj = Derived(5) print(obj.value, obj.doubled)
class Base { constructor(value) { this.value = value; } } class Derived extends Base { constructor(value) { super(value); this.doubled = value * 2; } } const derived = new Derived(5); console.log(derived.value, derived.doubled);
Both languages call the parent through super. JavaScript requires super(...) to run before you touch this in a subclass constructor — a rule Python does not impose.
Static methods
class MathHelper: @staticmethod def add(first, second): return first + second print(MathHelper.add(2, 3))
class MathHelper { static add(first, second) { return first + second; } } console.log(MathHelper.add(2, 3));
JavaScript marks class-level methods with the static keyword, where Python uses the @staticmethod decorator. Both are called on the class itself rather than on an instance.
Computed properties
class Circle: def __init__(self, radius): self.radius = radius @property def area(self): return 3.14159 * self.radius ** 2 print(round(Circle(2).area, 2))
class Circle { constructor(radius) { this.radius = radius; } get area() { return 3.14159 * this.radius ** 2; } } console.log(Number(new Circle(2).area.toFixed(2)));
A JavaScript get accessor is read like a plain attribute (circle.area, no parentheses) — exactly the behaviour Python's @property decorator provides.
String representation
class Point: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"({self.x}, {self.y})" print(str(Point(1, 2)))
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return `(${this.x}, ${this.y})`; } } console.log(String(new Point(1, 2)));
Defining toString() controls how an object converts to a string in JavaScript, the role Python's __str__ dunder method plays.
Error Handling
try / except vs. try / catch
try: result = 10 / 0 except ZeroDivisionError as error: print("caught:", error)
try { const result = 10 / 0; if (!isFinite(result)) { throw new Error("division by zero"); } } catch (error) { console.log("caught:", error.message); }
A crucial difference: dividing by zero in JavaScript yields Infinity rather than raising an error, so you must detect it yourself. JavaScript also has a single catch binding rather than Python's exception-type clauses.
Raising errors
def withdraw(amount): if amount < 0: raise ValueError("amount must be positive") return amount try: withdraw(-5) except ValueError as error: print(error)
function withdraw(amount) { if (amount < 0) { throw new Error("amount must be positive"); } return amount; } try { withdraw(-5); } catch (error) { console.log(error.message); }
JavaScript uses throw where Python uses raise. You can throw any value, but throwing an Error object is idiomatic because it carries a message and a stack trace.
finally
try: print("working") finally: print("cleanup")
try { console.log("working"); } finally { console.log("cleanup"); }
The finally block runs whether or not an error occurred, identically in both languages.
Custom exception classes
class ValidationError(Exception): pass try: raise ValidationError("invalid input") except ValidationError as error: print("validation:", error)
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } } try { throw new ValidationError("invalid input"); } catch (error) { console.log("validation:", error.message); }
A custom JavaScript error extends the built-in Error class and should set this.name so the type shows up in stack traces. Python subclasses Exception and often needs nothing more than pass.
with vs. callback cleanup
from contextlib import contextmanager @contextmanager def tag(name): print(f"<{name}>") yield print(f"</{name}>") with tag("p"): print("hello")
function withTag(name, body) { console.log(`<${name}>`); body(); console.log(`</${name}>`); } withTag("p", () => { console.log("hello"); });
Python's with statement and context managers guarantee setup and teardown around a block. JavaScript has no with for this purpose, so the common pattern is to pass a callback (or use try/finally).
Iterators & Generators
Generator functions
def count_up(limit): number = 1 while number <= limit: yield number number += 1 print(list(count_up(3)))
function* countUp(limit) { let number = 1; while (number <= limit) { yield number; number += 1; } } console.log([...countUp(3)]);
Both languages use the yield keyword for lazy generators. JavaScript marks a generator function with an asterisk (function*) and materializes it into an array with the spread operator instead of Python's list().
Pulling values one at a time
def squares(): for number in range(5): yield number * number values = squares() print(next(values)) print(next(values))
function* squares() { for (let number = 0; number < 5; number++) { yield number * number; } } const values = squares(); console.log(values.next().value); console.log(values.next().value);
JavaScript advances an iterator with .next(), which returns an object { value, done }. Python's next() built-in returns the value directly and raises StopIteration when exhausted.
Async & Promises
async / await
import asyncio async def main(): print("start") await asyncio.sleep(0) print("end") asyncio.run(main())
async function main() { console.log("start"); await new Promise(resolve => setTimeout(resolve, 0)); console.log("end"); } main();
Both languages spell asynchronous code with async and await. JavaScript's event loop is built into every runtime and starts automatically, so you simply call main(); Python requires an explicit asyncio.run() to start its loop.
Awaiting several tasks
import asyncio async def fetch(value): await asyncio.sleep(0) return value * 2 async def main(): results = await asyncio.gather(fetch(1), fetch(2), fetch(3)) print(results) asyncio.run(main())
async function fetchValue(value) { return value * 2; } async function main() { const results = await Promise.all([ fetchValue(1), fetchValue(2), fetchValue(3), ]); console.log(results); } main();
Promise.all() awaits a list of promises concurrently and resolves to an array of their results — the JavaScript counterpart to Python's asyncio.gather().
Modules
JSON serialization
import json data = {"name": "Alice", "age": 30} text = json.dumps(data) print(text) print(json.loads(text)["name"])
const data = { name: "Alice", age: 30 }; const text = JSON.stringify(data); console.log(text); console.log(JSON.parse(text).name);
JSON support is built into the global JSON object in JavaScript — no import needed — with JSON.stringify() and JSON.parse() mirroring Python's json.dumps() and json.loads().
Importing across files
# greetings.py def hello(name): return f"Hi, {name}" # main.py from greetings import hello print(hello("Alice"))
// greetings.js export function hello(name) { return `Hi, ${name}`; } // main.js import { hello } from "./greetings.js"; console.log(hello("Alice"));
Modern JavaScript uses ES modules: export marks what a file shares and import { name } from "./file.js" pulls it in — the counterpart to Python's from module import name. These examples span multiple files, so they cannot run in this single-file runner.