135 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			135 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								id: 587d7b87367417b2b2512b40
							 | 
						||
| 
								 | 
							
								title: Compare Scopes of the var and let Keywords
							 | 
						||
| 
								 | 
							
								challengeType: 1
							 | 
						||
| 
								 | 
							
								forumTopicId: 301195
							 | 
						||
| 
								 | 
							
								dashedName: compare-scopes-of-the-var-and-let-keywords
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# --description--
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When you declare a variable with the `var` keyword, it is declared globally, or locally if declared inside a function.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The `let` keyword behaves similarly, but with some extra features. When you declare a variable with the `let` keyword inside a block, statement, or expression, its scope is limited to that block, statement, or expression.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For example:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var numArray = [];
							 | 
						||
| 
								 | 
							
								for (var i = 0; i < 3; i++) {
							 | 
						||
| 
								 | 
							
								  numArray.push(i);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								console.log(numArray);
							 | 
						||
| 
								 | 
							
								// returns [0, 1, 2]
							 | 
						||
| 
								 | 
							
								console.log(i);
							 | 
						||
| 
								 | 
							
								// returns 3
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								With the `var` keyword, `i` is declared globally. So when `i++` is executed, it updates the global variable. This code is similar to the following:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var numArray = [];
							 | 
						||
| 
								 | 
							
								var i;
							 | 
						||
| 
								 | 
							
								for (i = 0; i < 3; i++) {
							 | 
						||
| 
								 | 
							
								  numArray.push(i);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								console.log(numArray);
							 | 
						||
| 
								 | 
							
								// returns [0, 1, 2]
							 | 
						||
| 
								 | 
							
								console.log(i);
							 | 
						||
| 
								 | 
							
								// returns 3
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This behavior will cause problems if you were to create a function and store it for later use inside a for loop that uses the `i` variable. This is because the stored function will always refer to the value of the updated global `i` variable.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								var printNumTwo;
							 | 
						||
| 
								 | 
							
								for (var i = 0; i < 3; i++) {
							 | 
						||
| 
								 | 
							
								  if (i === 2) {
							 | 
						||
| 
								 | 
							
								    printNumTwo = function() {
							 | 
						||
| 
								 | 
							
								      return i;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								console.log(printNumTwo());
							 | 
						||
| 
								 | 
							
								// returns 3
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								As you can see, `printNumTwo()` prints 3 and not 2. This is because the value assigned to `i` was updated and the `printNumTwo()` returns the global `i` and not the value `i` had when the function was created in the for loop. The `let` keyword does not follow this behavior:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								let printNumTwo;
							 | 
						||
| 
								 | 
							
								for (let i = 0; i < 3; i++) {
							 | 
						||
| 
								 | 
							
								  if (i === 2) {
							 | 
						||
| 
								 | 
							
								    printNumTwo = function() {
							 | 
						||
| 
								 | 
							
								      return i;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								console.log(printNumTwo());
							 | 
						||
| 
								 | 
							
								// returns 2
							 | 
						||
| 
								 | 
							
								console.log(i);
							 | 
						||
| 
								 | 
							
								// returns "i is not defined"
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`i` is not defined because it was not declared in the global scope. It is only declared within the for loop statement. `printNumTwo()` returned the correct value because three different `i` variables with unique values (0, 1, and 2) were created by the `let` keyword within the loop statement.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# --instructions--
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Fix the code so that `i` declared in the if statement is a separate variable than `i` declared in the first line of the function. Be certain not to use the `var` keyword anywhere in your code.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This exercise is designed to illustrate the difference between how `var` and `let` keywords assign scope to the declared variable. When programming a function similar to the one used in this exercise, it is often better to use different variable names to avoid confusion.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# --hints--
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`var` should not exist in code.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								(getUserInput) => assert(!getUserInput('index').match(/var/g));
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The variable `i` declared in the if statement should equal "block scope".
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								(getUserInput) =>
							 | 
						||
| 
								 | 
							
								  assert(
							 | 
						||
| 
								 | 
							
								    getUserInput('index').match(/(i\s*=\s*).*\s*.*\s*.*\1('|")block\s*scope\2/g)
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`checkScope()` should return "function scope"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								assert(checkScope() === 'function scope');
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# --seed--
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## --seed-contents--
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								function checkScope() {
							 | 
						||
| 
								 | 
							
								  var i = 'function scope';
							 | 
						||
| 
								 | 
							
								  if (true) {
							 | 
						||
| 
								 | 
							
								    i = 'block scope';
							 | 
						||
| 
								 | 
							
								    console.log('Block scope i is: ', i);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  console.log('Function scope i is: ', i);
							 | 
						||
| 
								 | 
							
								  return i;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# --solutions--
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								function checkScope() {
							 | 
						||
| 
								 | 
							
								  let i = 'function scope';
							 | 
						||
| 
								 | 
							
								  if (true) {
							 | 
						||
| 
								 | 
							
								    let i = 'block scope';
							 | 
						||
| 
								 | 
							
								    console.log('Block scope i is: ', i);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  console.log('Function scope i is: ', i);
							 | 
						||
| 
								 | 
							
								  return i;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 |