Functions and scope
JavaScript Scope
Learn how JavaScript scope decides where a variable is visible, covering global, function and block scope and how var differs from let and const.
Scope is the set of variables visible in a part of your program. JavaScript uses lexical scoping: a variable’s meaning comes from where you wrote it, not from where you call the code later.
We talk about global scope, function scope, and block scope. A variable declared outside any function or block attaches to the global object and is visible everywhere.
var, let, and const do not behave the same inside functions and blocks.
A var inside a function is visible through the whole function, like a parameter. A let or const inside a block is visible only in that block.
Blocks { } create scope for let and const, but not for var. Only a function body creates a new var scope.
Inside a function, var declarations hoist to the top of that function. You can reference the name before the assignment line, which often surprises people:
function run() {
console.log(`${name}`)
var name = 'Flavio'
}
run()
This prints undefined, because the engine effectively runs:
function run() {
var name;
console.log(`${name}`)
name = 'Flavio'
}
run()
let and const stay in the temporal dead zone until their line runs. The same example with let throws ReferenceError: name is not defined.
Inner functions can read variables from outer functions. That link is called a closure, and we cover it in the next lesson.
In non-strict mode, assigning to an undeclared name creates a global property. That is a common bug source. I run strict mode by default so the mistake fails fast.
A local declaration with the same name as a global shadows the global.
With var:
var name = 'Roger'
function run() {
console.log(`${name}`)
var name = 'Flavio'
}
run()
This prints undefined, not 'Roger'.
With let:
let name = 'Roger'
function run() {
console.log(`${name}`)
let name = 'Flavio'
}
run()
This throws ReferenceError: name is not defined, because the inner let is in the temporal dead zone for the whole block.
Try both snippets in the console. The difference is why I reach for let and const instead of var in new code.
Lesson completed