# 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); } ```