Slides
Scope
scope = all the variables that are visible from a given location in your code
including:
- local variables (
let
andvar
) - function parameters
- global variables
- top-level functions
Global Scope
If you declare a variable without a keyword (var
, let
, const
) then it is a global variable and can be seen and used by any line of code in your entire program
Global variables are very useful but also very dangerous. A mistake in any part of your program using a global variable could introduce a bug in any other part of your program using that global variable.
Implicit vs. Explicit globals
If you really want to use a global variable, you should do so explicitly, so other readers of your code will know that you did it intentionally.
JavaScript programs have a global object whose properties are available as global variables. In web browsers, the global object is named window
; in NodeJS, the global object is named global
.
// implicitly global
sendAnalytics = function(message) { ... }
// explicitly global
window.sendAnalytics = function(message) { ... }
Either of the above lines (in an HTML JS app) will allow any line in the entire rest of your program to call sendAnalytics('user clicked "unsubscribe" button')
Scope is a One-Way Mirror
scope is a one-way mirror -- inner scopes can see out, but outer scopes cannot see in
Variable Visibility
let name = 'Alice'; // this name is global
function beta() {
let name = 'Bob'; // this name is local to beta
console.log(name); // prints "Bob"
}
console.log(name); // prints "Alice"
function alpha() {
console.log(name); // alpha can see global var
// prints "Alice"
beta(); // alpha can see global function named beta
}
alpha();
Another scope diagram
What does this program print?
Scope Error
function gamma() {
var x = "declared inside gamma"; // x can only be used in gamma
console.log("Inside gamma");
console.log(x);
}
console.log(x); // Causes error
Closure Scope
JavaScript also supports lexical scope (aka "closure scope" or "nested scope") which means that variables defined above the current function may also be visible...
function sing() { // outer function
let numberOfBottles = 99
function bottlesOfBeer() { // inner function
return '' + numberOfBottles
+ ' bottles of beer on the wall'
}
while (numberOfBottles > 0) {
console.log(bottlesOfBeer())
numberOfBottles -= 1
}
}
numberOfBottles
is visible inside both sing()
and bottlesOfBeer()
Lexical Scope
Closures add a layer between global and local:
- local variables and parameters of nesting closures of the current function
This is called "lexical scope" because a given line of code can see all variables that are declared (= written = lexical) in the same code block, even if that code block is inside a different (nesting) function.
Nested Scopes
Every time you invoke a function, JS creates a new scope for that function
that points to the current scope
and so on recursively
Why Nested Scopes? 1
- so callbacks can access local variables just like their neighboring code can
Why Nested Scopes? 2
- nested functions, e.g.
function printGrid(grid) {
function printRow(rowNum) {
console.log(grid[rowNum].join(","));
}
let i = 0;
while (i<grid.length) {
printRow(i);
i = i + 1;
}
}
Why Nested Scopes? 3
- higher-order functions (functions that use other functions, like
map
orforEach
)
function countLetters(words) {
let total = 0;
words.forEach(function(word) {
total += word.length;
});
return total;
}
total
is visible inside the inner (callback) function as well as the outer (countLetters
), so forEach
can behave like other loops
Why Nested Scopes? 4
- private state encapsulation with IIFE's (this is tricky; for more detail, see the encapsulation lesson)
let count = (function() {
let value = 0; // private variable
let increment = function() {
value = value + 1;
console.log(value);
return value;
};
return increment;
})();
count() // prints and returns 1
count() // prints and returns 2
value // ReferenceError: value is not defined
Module Scope
- NodeJS introduced the concept of module scope to the JavaScript world.
- A variable defined at the "top" (left margin) of a file is visible to all other code in that file