Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Compare
  3. Python vs JavaScript
  4. Python vs JavaScript Variables

Python vs JavaScript Variables

How variable binding, scoping, and string interpolation differ between Python and JavaScript.

Declaration and Reassignment

Python uses bare assignment. A name springs into existence the moment you bind it to a value, and you can rebind it to a completely different type on the next line. There is no declaration keyword. JavaScript, by contrast, introduced three declaration keywords over the years: var (function-scoped, hoisted), let (block-scoped), and const (block-scoped, non-reassignable). The distinction matters because var leaks out of if-blocks and for-loops, a behavior that tripped up enough developers to motivate the ES6 additions. Python sidesteps the whole conversation: every variable is block-scoped to the enclosing function (or module), and there is no concept of hoisting. A name simply does not exist until execution reaches its assignment. One consequence of Python's approach is that you cannot declare a variable without assigning it. JavaScript's let x; creates an undefined binding, which has no Python equivalent. If you need a placeholder in Python, you assign None explicitly. The mental model shift is small but worth internalizing: Python treats names as labels stuck onto objects, while JavaScript treats variables as boxes that hold values (or references).

Basic variable assignment

Python
name = "Ada"
age = 30
name = "Grace"  # rebind freely
JavaScript
let name = "Ada";
let age = 30;
name = "Grace"; // reassignment OK with let

Constants

Python
MAX_RETRIES = 5  # convention only, not enforced
# MAX_RETRIES = 10  # nothing stops you
JavaScript
const MAX_RETRIES = 5;
// MAX_RETRIES = 10; // TypeError at runtime
Warm-up1 / 2

Can you write this from memory?

Write an expression that splits `item` by commas into a list of strings

Python: Python String Methods Practice: f-strings, split, join, strip, slicing →JavaScript: JavaScript String Methods Practice →

Type Coercion and Dynamic Typing

Both languages are dynamically typed, but they handle type mismatches differently. Python raises a TypeError when you try to add a string and an integer. JavaScript silently coerces one operand to match the other, producing results that have become a running joke in the developer community ("1" + 2 === "12"). This design choice reflects JavaScript's origins as a forgiving browser scripting language: Brendan Eich prioritized keeping pages running over stopping execution. Python's philosophy -- errors should never pass silently -- takes the opposite stance. The practical fallout is that Python developers moving to JavaScript need to adopt defensive habits: strict equality (===) instead of loose equality (==), explicit Number() or String() conversions, and linter rules that flag implicit coercion. Going the other direction, JavaScript developers arriving in Python discover that the language simply refuses to guess what you meant, which eliminates an entire category of bugs at the cost of occasional verbosity.

String plus number

Python
# "Age: " + 30  # TypeError
"Age: " + str(30)  # => "Age: 30"
JavaScript
"Age: " + 30   // => "Age: 30" (coerced)
"Age: " + String(30) // explicit

Equality comparison

Python
1 == True   # => True (bool is int subclass)
1 == "1"   # => False
JavaScript
1 == true    // => true  (coerced)
1 === true   // => false (strict)
1 == "1"     // => true  (coerced)

String Interpolation

Python f-strings (3.6+) and JavaScript template literals (ES6) solve the same problem -- embedding expressions inside strings -- but the delimiter syntax differs. Python prefixes the string with f and uses curly braces: f"Hello {name}". JavaScript wraps the whole string in backticks and uses dollar-brace: `Hello ${name}`. Both support arbitrary expressions inside the interpolation brackets, including method calls, ternaries, and arithmetic. One difference that catches people: Python f-strings can include format specifiers after a colon (f"{price:.2f}"), while JavaScript template literals rely on external calls like toFixed(2). Another gap is multi-line strings. JavaScript template literals preserve newlines by default, making them handy for HTML fragments. Python's triple-quoted strings ("""...""") serve the same role, but they are a separate feature from f-strings, meaning you combine them as f"""...""". The two approaches end up roughly equivalent in power, though the ergonomics of formatting numbers and dates still tilt toward Python.

Basic interpolation

Python
name = "Ada"
print(f"Hello, {name}!")
# => Hello, Ada!
JavaScript
const name = "Ada";
console.log(`Hello, ${name}!`);
// => Hello, Ada!

Expression inside interpolation

Python
price = 19.995
print(f"Total: {price:.2f{'}'}")
# => Total: 20.00
JavaScript
const price = 19.995;
console.log(`Total: ${price.toFixed(2)}`);
// => Total: 20.00
Warm-up1 / 2

Can you write this from memory?

Write an expression that splits `item` by commas into a list of strings

Python: Python String Methods Practice: f-strings, split, join, strip, slicing →JavaScript: JavaScript String Methods Practice →

Scope Rules

Python has four scope levels: local, enclosing function, global, and built-in (the LEGB rule). JavaScript with let and const has block scope inside any curly-brace block, plus function scope and global scope. The difference shows up most clearly in loops. A Python for-loop variable leaks into the enclosing function scope -- after for i in range(5), the name i is still accessible and holds 4. JavaScript's let in a for-loop creates a fresh binding per iteration, which is why closures inside loops work as expected with let but produced the classic "all callbacks print 5" bug with var. Python developers writing closures over loop variables need the same awareness: capturing a loop variable by reference in a lambda grabs the final value unless you use the default-argument trick (lambda i=i: i). The scope differences also surface in variable shadowing. Python disallows accidental shadowing -- assigning to a variable inside a function creates a local, even if a global of the same name exists, and reading it before assignment raises UnboundLocalError. JavaScript happily shadows with a new let declaration in any inner block.

Loop variable leaking

Python
for i in range(3):
    pass
print(i)  # => 2 (still accessible)
JavaScript
for (let i = 0; i < 3; i++) {}
// console.log(i); // ReferenceError

Closure in a loop

Python
fns = [lambda i=i: i for i in range(3)]
print(fns[0]())  # => 0
JavaScript
const fns = [];
for (let i = 0; i < 3; i++) {
  fns.push(() => i);
}
console.log(fns[0]()); // => 0

Practice Both Languages

10 free exercises a day. No credit card required. Build syntax muscle memory with spaced repetition.

Free forever. No credit card required.

← Back to Python vs JavaScript
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.