Practice: Scope & Conditionals in JS
A small browser game I built to practice JavaScript scope, conditionals, and DOM events/updates.
Click Rock / Paper / Scissors to play rounds against a computer opponent.
- Scores update in the UI after each round
- Focus of this repo: how functions see variables (scope), how if/else logic decides winners, and how event listeners trigger code
I used this as a sandbox to understand:
- Function vs block scope –
let/constinsideif/switch/functions and their visibility - Conditionals – strict comparison (
===) and correct use of&&/|| - DOM updates – writing to elements with
textContentafter state changes - Event listeners –
addEventListenervs inlineonclick, and the difference between passing a function reference vs calling it immediately
- Clone the repo
- Open
index.htmlin a browser (no build step required) - Click Start Game, then choose Rock / Paper / Scissors
rock-paper-scissors/
├── index.html # Markup with buttons and output containers
├── style.css # Basic styles
└── script.js # Game logic (computer choice, round handling, UI updates)
Computer choice:
Math.random() → getRandomInt(3) → switch to "Rock" | "Paper" | "Scissors"
Game state:
playerWins, cpuWins, roundCounter stored in the gameLoop closure so roundLoop can read/update them.
Round logic:
In roundLoop(playerChoice):
- Compare
playerChoiceandcpuChoicewith strict equality - Use AND (
&&) for "A beats B" checks - Increment the right score, recompute
currentScore, and update the DOM (textContent) after changes
Events:
Buttons use addEventListener("click", () => roundLoop("Rock")) (arrow wrapper defers the call until click).
- Variables declared inside
if/switchblocks withlet/constdon't leak out - Returning from inside an
ifreturns from the enclosing function, not just the block - Event handlers run later, so you can't "return from
gameLoop" once it's done; instead use shared flags (e.g.,isOver) or remove listeners
===over==to avoid coercion bugs- Correct use of
&&vs||in win conditions - Order of checks matters (early return ends the function)
addEventListener("click", handler)expects a function referencehandler()calls immediately;() => handler()delays until the click- DOM isn't reactive—reassign text after state changes
- Game reset/disable after win is minimal
- No persistence or animations
- UI is intentionally simple
MIT (feel free to use/modify while learning)