# Node/JavaScript Concepts
## Scope
Where you are able to access data in your program
```javascript=
let hello = 'hello' // hello is global
function cool () { // cool is global
let awesome = 'awesome' // awesome is inside the cool function (function scope)
}
for (let i = 0...) // i is inside the for loop (block scope)
for (var j = 0...) // because j is declared with var, j is in the global scope
// In ES5, there is no such thing as block scope, and var would either be in function scope or global scope. But there is no function here since it's just a for loop
```
## Closure
What is closure and give an example?
Closure is the ability of a function to "remember" its lexical scope even though that function is being run outside of that lexical scope.
```javascript=
function outer () {
let counter = 0
function inner() {
return counter += 2
}
return inner
}
let newInstance = outer()
newInstance() // Increment counter
newInstance() // Increment counter
```
## Event Loop
The Event Loop is how Node/JavaScript deals with asynchronous code. When functions execute, they get placed onto the call stack. If JavaScript encounters an asynchronous call such as a `setTimeout`, it gets placed in the Event Queue while the program finishes running. The Event Loop keeps checking if the call stack is empty. If it is not, then "tick" again, meaning, go through the process over again. If it is, and there is something in the Event Queue, then push that onto the call stack to be run.
Note: In ES6 there is now something called the Promise Queue. Check this [article](https://blog.sessionstack.com/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with-2f077c4438b5?gi=4a31b2d14e0b) for more info
### Write an Algorithm that Simulates the Main Functionality of the Event Loop
```javascript=
// To implement the 'eventQueue' you can assume that it is a Queue without writing that functionality
// OR simply use an array that acts as a queue by only using '.shift()'
let eventQueue = []
// Assume the call stack as well
let callStack = []
// ensure the event loop keeps going "forever"
while (true) {
// perform a "tick"
// Check if there is something in the queue as well as if the call stack is empty
if (eventQueue.length > 0 && !callStack.length ) {
// get the next event in the queue
let event = eventQueue.shift()
callStack.push(event)
// now, execute the next event
//this block does all of the checks to ensure that the event is a function that can run appropriately
try {
let eventToCall = callStack.pop()
eventToCall()
}
catch (err) {
console.log(err)
}
}
}
```
### Closure + Event Loop + `var` Gotcha
What will the following code output?
```javascript
var arr = [10, 12, 15, 21]
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log('Index: ' + i + ', element: ' + arr[i])
}, 3000);
}
```
#### Solution
Index: 4, element: undefined (printed 4 times)
It's important to note the `var`. The scope of `var` depends on where it is defined. Since, in ES5, there was no concept of block scope, `var` would either be in function scope or global scope. Since there is no function defined here as the for loop is considered a block, `var` exists globally
The setTimeout function creates a function (the closure) that has access to its outer scope, which is the loop that contains the index i. However, that same functions gets put on the event loop.
After 3 seconds go by, the function returns from the event loop, gets placed on the stack and executes and it prints out the value of i. The problem is that the for loop has already been looped through. Remember the loop goes through the entire length of the array which is 4 before the condition is actually broken. arr[4] does not exist, which is why you get undefined.
```javascript
let arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
// pass in the variable i so that each function
// has access to the correct index
// this is called in IIFE
setTimeout(function(i_local) {
return function() {
console.log('The index of this number is: ' + i_local);
}
}(i), 3000);
}
```
OR
```javascript
let arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {
// using the ES6 let syntax, it creates a new binding
// every single time the function is called
// read more here: http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads
setTimeout(function() {
console.log('The index of this number is: ' + i);
}, 3000);
}
```