5. Variables and Scope
Variable Declaration
ECMAScript provides three ways to declare variables:
var (Legacy)
var x = 10;
var y; // undefined
y = 20;
Problems with var:
- Function scope (not block scope)
- Can be redeclared
- Hoisted to top of function
let (ES6+)
let x = 10;
let y; // undefined
y = 20;
// Cannot redeclare in same scope
// let x = 5; // Error!
const (ES6+)
const PI = 3.14159;
const CONFIG = { debug: true };
// Must be initialized
// const x; // Error!
// Cannot reassign
// PI = 3.14; // Error!
// But can modify object properties
CONFIG.debug = false; // OK
Scope
Global Scope
Variables declared outside any function:
let globalVar = "I'm global";
function test() {
console.log(globalVar); // Accessible
}
Function Scope
Variables declared with var are function-scoped:
function example() {
var functionScoped = "inside function";
console.log(functionScoped); // OK
}
// console.log(functionScoped); // Error: not defined
Block Scope
Variables declared with let and const are block-scoped:
if (true) {
let blockScoped = "inside block";
console.log(blockScoped); // OK
}
// console.log(blockScoped); // Error: not defined
Hoisting
var Hoisting
console.log(hoisted); // undefined (not error!)
var hoisted = "I'm hoisted";
Equivalent to:
var hoisted;
console.log(hoisted); // undefined
hoisted = "I'm hoisted";
let/const Hoisting
// console.log(notHoisted); // Error: Cannot access before initialization
let notHoisted = "I'm not hoisted";
Temporal Dead Zone (TDZ)
The period between entering scope and variable declaration:
{
// TDZ starts here
console.log(x); // Error: x is in TDZ
let x = 5; // TDZ ends here
}
Best Practices
- Use
constby default: Prevents accidental reassignment - Use
letwhen you need to reassign: For counters, loops, etc. - Avoid
var: Uselet/constinstead - Declare variables at the top of scope: Improves readability
- Use meaningful names:
userNameinstead ofu
Examples
Counter with let
function countToTen() {
for (let i = 1; i <= 10; i++) {
console.log(i);
}
// i is not accessible here
}
Configuration with const
const APP_CONFIG = {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3
};
// APP_CONFIG = {}; // Error: cannot reassign
APP_CONFIG.timeout = 10000; // OK: can modify properties
Block scoping in loops
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // Prints 0, 1, 2
}
for (var j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100); // Prints 3, 3, 3 (closure issue)
}
Next Steps
Understanding variables and scope is crucial. Next, let's explore data types in ECMAScript.