jypi
  • Explore
ChatWays to LearnMind mapAbout

jypi

  • About Us
  • Our Mission
  • Team
  • Careers

Resources

  • Ways to Learn
  • Mind map
  • Blog
  • Help Center
  • Community Guidelines
  • Contributor Guide

Legal

  • Terms of Service
  • Privacy Policy
  • Cookie Policy
  • Content Policy

Connect

  • Twitter
  • Discord
  • Instagram
  • Contact Us
jypi

© 2026 jypi. All rights reserved.

CS50 - Web Programming with Python and JavaScript
Chapters

1Orientation and Web Foundations

2Tools, Workflow, and Git

3HTML5 and Semantic Structure

4CSS3, Layouts, and Responsive Design

5Python Fundamentals for the Web

6Flask, Routing, and Templates

7Data, SQL, and ORM Patterns

8State, Sessions, and Authentication

9JavaScript Essentials and the DOM

Language syntax essentialsVariables and scoping rulesFunctions and closuresObjects and prototypesArrays and higher order methodsES6 modules and toolingThe event loop modelDOM selection and traversalDOM manipulation patternsEvents and event delegationBrowser storage APIsTimers and intervalsError handling and try catchTemplate literals and destructuringClasses and inheritance

10Asynchronous JS, APIs, and JSON

11Frontend Components and React Basics

12Testing, Security, and Deployment

Courses/CS50 - Web Programming with Python and JavaScript/JavaScript Essentials and the DOM

JavaScript Essentials and the DOM

24673 views

Use modern JavaScript to make pages interactive and manipulate the DOM safely and efficiently.

Content

2 of 15

Variables and scoping rules

JavaScript Variables and Scoping Rules Explained (CS50 Web)
6811 views
beginner
humorous
computer science
javascript
web-development
gpt-5-mini
6811 views

Versions:

JavaScript Variables and Scoping Rules Explained (CS50 Web)

Watch & Learn

AI-discovered learning video

YouTube

Start learning for free

Sign up to save progress, unlock study materials, and track your learning.

  • Bookmark content and pick up later
  • AI-generated study materials
  • Flashcards, timelines, and more
  • Progress tracking and certificates

Free to join · No credit card required

JavaScript Variables and Scoping Rules — the backstage pass to your app's memory

Imagine you stored a user's session token in a global variable. Then some other script (or a sneaky library) overwrote it. Congratulations — you just created a security bug and a very unhappy user.

(You read the previous CS50 section on handling user state securely and authentication. Good — this is where those ideas meet the language-level rules that make or break safe state management.)


What this is and why it matters

Variables and scope determine where your data lives, who can see it, and for how long. In web apps this directly affects:

  • Security: sensitive values that leak into global scope are easier to tamper with.
  • Correctness: bugs like unexpected overwrites and surprising values come from misunderstanding scope and hoisting.
  • Memory & lifecycle: closures can keep things alive longer than you expect.

So if you want robust authentication, safe session handling, and fewer hair-pulling bugs — learn scoping.


The three players: var, let, const

Micro explanation

  • var — old-school, function-scoped, hoisted. Can cause surprise leaks.
  • let — block-scoped, not accessible before declaration (temporal dead zone).
  • const — block-scoped, must be initialized, binding cannot be reassigned (but objects it points to can be mutated).

Always prefer const by default, let when you must reassign, and avoid var unless you have a very specific reason.

// var example (hoisting):
console.log(x); // undefined (not ReferenceError)
var x = 5;

// let/const example (temporal dead zone):
console.log(y); // ReferenceError
let y = 10;

Hoisting — the illusion that declarations move

JavaScript hoists declarations (not initializations). With var, the declaration is lifted to the top of its function scope, but the assignment stays where it was.

Example that bites you:

function getUser() {
  console.log(token); // undefined
  var token = window.localStorage.getItem('token');
}

You might think token is unavailable before the line that sets it. But var makes it exist (as undefined) from the start — which can hide bugs.

With let/const you get a ReferenceError instead, which often helps catch problems earlier.


Function scope vs block scope

  • Function scope (var): variables declared with var are visible anywhere inside the function.
  • Block scope (let/const): variables declared with let or const are only visible inside the nearest { ... } block (if, for, while, etc.).

The infamous for-loop closure bug

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 10); // prints 3, 3, 3
}

for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 10); // prints 0, 1, 2
}

Why? var i is shared across iterations (function scope), so by the time callbacks run i is 3. let creates a fresh binding per iteration. This is a practical reason to prefer let in loops.


Closures: private variables and long-lived references

A closure lets a function access variables from an outer scope even after that outer function has finished running. This is powerful and subtle.

Use case: module pattern (privacy)

const Auth = (function() {
  let token = null; // private

  return {
    setToken(t) { token = t; },
    getToken() { return token; }
  };
})();

Auth.setToken('abc');
console.log(Auth.getToken()); // 'abc'

This pattern keeps token out of global scope — a win for security. But closures also keep token alive in memory until the closure itself is collectible.


Temporal Dead Zone (TDZ) — why some access raises errors

Accessing a let/const binding before its declaration throws a ReferenceError. This is the TDZ and prevents subtle hoisting bugs.

function weird() {
  console.log(a); // ReferenceError
  let a = 2;
}

TDZ helps you catch mistakes early — another reason let/const are preferable.


Global scope: the land of accidents

Anything attached to the global object (window in browsers) is accessible everywhere. That makes globals great for convenience and terrible for security and maintenance.

Bad idea:

window.currentUserId = 'sensitive-id';

Any script can read or overwrite that. Instead: keep sensitive info on the server, or in scoped closures/modules and only expose controlled APIs to the rest of your code.


Practical rules for CS50 web projects (and real life)

  1. Default to const. Use let only for variables that change. Avoid var.
  2. Never store sensitive session/auth data in globals. Store tokens in secure HTTP-only cookies or server-side session stores. If you must store anything client-side, minimize and protect it.
  3. Encapsulate module state using closures, ES modules, or classes. Expose minimal API methods that validate input.
  4. Beware third-party scripts. They can access globals. Don't attach secrets to window.
  5. Use strict mode (automatically in ES modules): catches silent errors and forbids accidental globals.
  6. Mind closures: they are great for privacy but can keep data alive longer than intended.

Quick reference: behavior summary

  • var: function-scoped, hoisted (initialized to undefined), can be redeclared
  • let: block-scoped, hoisted but uninitialized (TDZ), cannot redeclare in same scope
  • const: block-scoped, must initialize, binding immutable (value may be mutable if object)

A real-world security example

Imagine you tried to cache a token client-side during debugging:

var token = 'temporary-auth';
// some other script accidentally reassigns token = null
// your app loses auth state or accepts malicious value

If instead token were kept inside a module closure and only accessible through controlled getters/setters, an accidental overwrite would be far less likely.


Key takeaways

  • Scope is your first line of defense against accidental leaks and overwrites.
  • Prefer const and let over var for predictable behavior and fewer surprises.
  • Avoid global variables for auth or sensitive state; keep secrets server-side or in HTTP-only cookies.
  • Use closures and modules to create private state and controlled APIs.

"Treat variables like people in a party: keep strangers out of your private conversations, and don't let everyone shout into the room." — your slightly dramatic CS50 TA

If you master scoping, hoisting, and closures, you'll write code that's easier to reason about, harder to exploit, and—bonus—less likely to cause 2 AM debugging spirals.


Further reading: MDN on var/let/const, articles on temporal dead zone, and patterns for secure client-side state. Try refactoring one of your project files to remove var and globals — it's a great exercise.

Flashcards
Mind Map
Speed Challenge

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Ready to practice?

Sign up now to study with flashcards, practice questions, and more — and track your progress on this topic.

Study with flashcards, timelines, and more
Earn certificates for completed courses
Bookmark content for later reference
Track your progress across all topics