Skip to content

Variable Scoping

Open the editor to see scoping in action.

How Your Code Executes

javascript
new Function('time', 'dt', 'state', 'w', 'h', '__modules',
  `"use strict"; return (() => { YOUR_CODE })()`
)

Every frame is a fresh strict-mode function call.

let and const — Reset Every Frame

javascript
let counter = 0;
counter++;

return {
  text: { counter },  // always "1"
};

They cannot accumulate values across frames.

var — Also Scoped

Strict mode keeps var function-scoped. No globals leak out of the IIFE.

Why state Exists

javascript
// WRONG — never accumulates
let x = 100;
x += 50 * dt;

// RIGHT
state.x = (state.x ?? 100) + 50 * dt;

Common Patterns

javascript
if (!state.init) {
  state.x = 100;
  state.init = true;
}
state.x += 50 * dt;

Nullish coalescing

javascript
state.x = (state.x ?? 100) + 50 * dt;

Avoid || for numbers

javascript
// BUG if 0 is valid
state.x = state.x || 100;

// Prefer
state.x = state.x ?? 100;

Helpers in the Entry File

javascript
function addParticle(x, y) {
  state.particles.push({
    x, y,
    vx: (Math.random() - 0.5) * 100,
    vy: -50 - Math.random() * 100,
    life: 1,
  });
}

Redefined each frame — negligible cost. For shared logic across files, use modules and pass dt / state as arguments (modules do not see frame globals).