Skip to content

Commit a64d87f

Browse files
committed
Updated handouts
1 parent 174617c commit a64d87f

File tree

5 files changed

+421
-4
lines changed

5 files changed

+421
-4
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
![](headings/introjs5.3.jpg)
2+
3+
# Scope in JavaScript
4+
5+
I've mentioned the term **scope** a couple of times in this course and I haven't really gone into details about defining it but I'd like to show you more about how scope work in JavaScript and why you need to keep it in mind.
6+
7+
# Functions with Var Statements
8+
9+
You might have noticed when we've been making functions, we've been creating variables inside those functions to declare local variables such as counters or things that'll be in the return value. Let's go back to one of the examples that we used in the last set of exercises.
10+
11+
```js
12+
var greeting = "Hello";
13+
var items = ["World"];
14+
15+
function greeter(str, arr) {
16+
var counter; // local variable in the function
17+
for (counter = 0; counter < arr.length; counter++) {
18+
console.log(str + " " + arr[counter]);
19+
}
20+
}
21+
22+
greeter(greeting, items);
23+
// "Hello World"
24+
25+
console.log(counter);
26+
// "error" (ReferenceError: counter is not defined)
27+
```
28+
29+
If we were to try to `console.log` the `counter` variable outside of the function `greeter`, it will be `undefined`. `counter` does not exist outside the scope of the function `greeter`.
30+
31+
In JavaScript, you create a new scope every time that you create a new function. And scope is defined such that variables created within the scope of a function using the `var` keyword only exist within that function, and can't be accessed outside of that function.
32+
33+
# Var Statements Limit Scope
34+
35+
The reason that works is because we're using the `var` statement to create our variables. The `var` statement limits the scope of the variable to wherever to it was declared. A variable declared without a `var` statement is valid in JavaScript but it will be applied to the global scope which means that it will exist outside the scope of your script and be available inside of the script as well but that can cause problems.
36+
37+
I'm going to show you how global variables work and then I'm going to tell you never to use them but you need to understand what happens with global variables. We're going to create a quick function and it's just going to be called `example`.
38+
39+
```js
40+
function example() {
41+
var local = "Only available inside example()"; // with var
42+
global = "Available anywhere once executed"; // without var
43+
}
44+
45+
console.log(local);
46+
// "error" (ReferenceError: local is not defined)
47+
48+
console.log(global);
49+
// "error" (ReferenceError: local is not defined)
50+
51+
example(); // execute the example function
52+
53+
console.log(local);
54+
// "error" (ReferenceError: local is not defined)
55+
56+
console.log(global);
57+
// "Also available anywhere"
58+
```
59+
60+
The problem with that is that we don't know at any point in the program whether `example` has been executed. `global` could be defined or not defined and we have no way of understand that, we don't have a modular approach to how this function works, if it's plying and creating global variables. This is one of the many reasons that coding environments that checkthe validity of your job JavaScript code while you're coding will tell you that variables created without the `var` keyword should not be used.Variables can be inherited by functions from their parent scope.
61+
62+
# Variable Scope is Inherited One Way
63+
64+
Variables can be inherited by functions from their parent scope and functions inherit all of the variables that existin the scope in which they were created which makes sense, because a function needs access to the variables that were available at the time that it was created.
65+
66+
```js
67+
var phrase = "always available";
68+
69+
function example() {
70+
var local = "Only available inside example()";
71+
console.log(phrase);
72+
console.log(local);
73+
}
74+
75+
example();
76+
// "always available"
77+
// "Only available inside example()"
78+
79+
console.log(phrase);
80+
// "always available"
81+
82+
console.log(local);
83+
// "error" (ReferenceError: local is not defined)
84+
```
85+
86+
Understanding the difference between a local variable and a variable that exists outside of the scope of a function will help you avoid undefined variable errors like that.
87+
88+
# Declaring Variables First
89+
90+
You might also have noticed that inside of each function fact inside each of each program that we've been writing, we've been declaring all of our variables at the very top of the code that we're writing. JavaScript will hoist the variable declarations to the top of whatever scope that that variable exists in. For that reason, even though JavaScript will let you declare variables anywhere in the body of your code, it's a very good idea to start each function or script by declaring any variables you plan to use within that scope.
91+
92+
Any time you come across a variable you need to define, declare it at the top of whatever scope it's going to live in. It will help you keep track of where your variables live. Understanding variable hoisting can help you some of the trickier problems to track down in JavaScript.
93+
94+
```js
95+
// one script that uses a counter
96+
count = 5;
97+
98+
// another script that sets count based on a price
99+
function thousands(price) {
100+
count = price * 1000;
101+
return(count);
102+
}
103+
thousands(50);
104+
105+
// another script that uses count for an iterator
106+
for (count = 0; count < 6; count++) {
107+
// do something six times
108+
}
109+
110+
// A whole bunch of code later...
111+
112+
console.log(count);
113+
// could be anything
114+
```
115+
116+
Variable hoisting comes about because when JavaScript processes a script to run it, the compiler does two passes. First it goes through all of the code, defines all of the functions, and declares all of the variables. Then on the second pass, it goes through and runs the statements in order. Functions are declared and variables are declared and hoisted to the top of their scope during the first pass before any execution happens.
117+
118+
# The Global Scope
119+
120+
So when considering what scope a variable is going to live in, JavaScript first looks to see what it's container is. If it's not contained within a function, that variable is assigned to the global scope. All scripts that are being executed at the same time share space in a single global object. That global object is called window in browsers, and it's called global on the server, for example, in Node. Because of this,you need to be careful about assigning variables to this global scope.
121+
122+
```js
123+
var count = 5;
124+
125+
console.log(count);
126+
// 5
127+
console.log(window.count);
128+
// 5
129+
130+
window.count = 10;
131+
console.log(count);
132+
// 10
133+
console.log(window.count);
134+
// 10
135+
```
136+
137+
Every script that runs simultaneously in your browseris going to have access to the `window` object, just like every script that runs simultaneously on your server is going to have access to the global object.
138+
139+
# What's Wrong with Global Scope?
140+
141+
So, what's wrong with assigning variables to the global scope? The problem is that different parts of your code may reuse a common variable name. And no matter how careful you think you're being, this can happen even within the smallest and most ordinary of scripts. Imagine how much more complicated that could be if you're simultaneously running multiple scripts from multiple programmers, all of them loaded on the same page at the same time.
142+
143+
```js
144+
function predefined() {
145+
var before = 5; // declared and initialized
146+
var after = 10; // declared and initialized
147+
return(before + after);
148+
}
149+
150+
function undefinedAfter() {
151+
var before = 5; // declared and initialized
152+
return(before + after);
153+
var after = 10; // initialized, declaration hoisted
154+
}
155+
156+
function undeclaredAfter() {
157+
var before = 5; // declared and initialized
158+
return(before + after);
159+
}
160+
161+
console.log(predefined());
162+
// 15
163+
164+
console.log(undefinedAfter());
165+
// NaN
166+
167+
console.log(undeclarededAfter());
168+
// error: ReferenceError: after is not defined
169+
```
170+
171+
The question is, after doing all of those things, what's the value of `count` and the point is that we don't really have any way of knowing. Depending on what happened in that bunch of other code and what order these things were declared in, because we use the same count variable over and over again, all in the same scope, we've lost track of what the value of `count` actually is going to be.
172+
173+
This gets even worse if we leave off the `var` keyword on `count`. No matter how carefully we've managed our scripts, the variable `count` could exist anywhere in any of the scripts that we're running.
174+
175+
Basically, you want to be careful not to set variables on the global scope and you want to pay attention to warnings that tell you not to use global scope.
176+
177+
# Ways to Isolate Variable Scope
178+
179+
There are some ways to isolate variable scope and these are good practices to keep in mind when you're coding. Keep local variables out of the global object by declaring them inside of functions, wrap all of your code inside of an immediately invoked function expression or write your code inside of custom objects that contain all of the methods you're going to be using and encapsulate them that way.
180+
181+
I'll give you an example of each of these three ways to encapsulate your variable scope.
182+
183+
```js
184+
// local to a function
185+
function thousands(price) {
186+
var count = price * 1000;
187+
}
188+
189+
// immediately invoked function expressions
190+
(function() { // start a function expression
191+
var count;
192+
for (count = 0; count < 6; count++) {
193+
// do something six times
194+
}
195+
}()); // execute that function expression
196+
197+
// local to a private object (less safe)
198+
var myApp = {};
199+
myApp.count = "Hello".length;
200+
201+
console.log(count);
202+
// error: ReferenceError: count is not defined
203+
```
204+
205+
The first way we've been talking about when you declare a function, declare your variables inside of that function using the `var` keyword. This way you can be confident that those variables will only exist within the scope of that function.
206+
207+
A second way is by creating an immediately invoked function expression. So we execute the function as soon as it's declared and we're going to do to that the same way we execute any function with a set a parentheses and we end with a semicolon.
208+
209+
A third way is to start by declaring an object that's going to contain all of the code for your application.
210+
211+
Being a good developer citizen while you're programming in JavaScript, means understanding how you isolate your variables from the global scope, so that your variables don't leak into other people's programs and vice versa.
133 KB
Binary file not shown.

0 commit comments

Comments
 (0)