6. Function Scope, Block Scope and Lexical Scope
Tags: javascript, webdev, beginners, programming
Published: 2022-01-19 13:04:49

### **Articles**

- [JavaScript Functions — Understanding The Basics — Brandon Morelli](https://codeburst.io/javascript-functions-understanding-the-basics-207dbf42ed99) done
- [The battle between Function Scope and Block Scope — Marius Herring](http://www.deadcoderising.com/2017-04-11-es6-var-let-and-const-the-battle-between-function-scope-and-block-scope/) done var problem
- [JavaScript Scope and Closures — Zell Liew](https://css-tricks.com/javascript-scope-closures/) done
- [When to use a function declaration vs. a function expression ― Amber Wilkie](https://medium.freecodecamp.org/when-to-use-a-function-declarations-vs-a-function-expression-70f15152a0a0) done
- [Functions / Function scope ― MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#function_scope) main for closure

---
## Functions
- Functions are executed when they are called/invoked.
- Functions always returns value. If value isn't given, it returns `undefined`.
- Functions are objects.
### Defining functions
#### Function Declaration
- Named functions are declared.
- Hoisted
``` jsx
add(1,2) // 3

function add(value1, value2) {
    console.log(value1 + value2);
    return 1;
  }
```
- Created in global scope
#### Function Expression
- Named or anonymous function are possible.
- Not hoisted
``` javascript
addNumber(2,3); // "ReferenceError: Cannot access 'addNumber' before initialization

const addNumber = function (value1, value2) {
    console.log(value1 + value2);
    return 1;
  }
```
#### Arrow function
- Shorter syntax
- Not create own `this` value
``` jsx
const addNumber = (value1, value2) => {
    console.log(this);
    return this;
  }

addNumber(2,3); // [object Window]
```

### IIFE(Immediately invoked function expressions)
``` jsx
((value1, value2) => {
    console.log(value1 + value2);
    return 1;
  })(2,3);
```
---
## Scope
Scope defines what variable we can access to.
### Global scope
Variables declared outside function, block are all contained in global scope. 
#### POLE; Principle of least exposure
We should minimize the exposure of variables registered in each scope. It means that we should try our best to avoid delcaring variables in global scope. Why?
- Naming Collision

If we declare same name variable twice, it makes some problems. First, with `var`, the variable would shadow the previous value assigned. Second, with `let` and `const` , it would give error.
- Unexpected behavior

Let' say that I declared data array in global scope. Then other developer can easily alter the value. 
- Unintended dependency

Let's say that I declared data array for specific function's argument. If other developer uses data array, unintended dependency has occured. If I plan to change this array into object, many parts using this array should be changed.
### Local scope
#### Function scope
`var` is function scope. Precisely, Javascript had only function scope before ES6. It exists within the scope of function it's declared.
``` jsx
const password = "3";

function checkIf(input) {
  if(input == password) {
    console.log(true);
  }
  else {
    console.log(false);
  }
}
console.log(password); // 3
checkIf(3); // true
```
Here, `input` parameter is declared in function `checkIf` scope. `password` variable is declared in global scope which is very vulnerable. So, How can we hide the `password`, still accessing to `checkIf` function?


``` jsx
function hidePassword() {
  const password = "3";
  
  return checkIf;
  function checkIf(input) {
    if(input == password) {
      console.log(true);
    }
    else {
      console.log(false);
    }
}
}

console.log(password); // ReferenceError: password is not defined
const testCase = hidePassword();
testCase(3); // true
```
We hide the `password` in `hidePassword` function. As `checkIf` function is inside the `hidePassword` function and returned, we can access to this function.

``` jsx

const testCase =(()=>{
  const password = "3";
  return checkIf;
  function checkIf(input) {
    if(input == password) {
      console.log(true);
    }
    else {
      console.log(false);
    }
  }
})();

testCase(3); // true
```
By using IIFE, we can write it more clearer, shorter.
#### Block scope
As `let` and `const` introduced in ES6, both keywords are block scope. `{}` becomes scope if it contains `let` or `const`.
``` jsx
function add(value1, value2) {
  {
    let value3 = 4;
  }
  console.log(value3);
}

add(1,2); // "ReferenceError: value3 is not defined"

```
We have mentioned about POLE. So, it's best to put `let` or `const` declared variable in block scope as possible. 

---
### What is Lexical scope?
JS program processes in two phases; Compilation & Execution.
In compilation, JS Engine parses through the code and checks which variables corresponds to which scope. This means that scope of variables are determined before execution, which we call it **lexical scope**.
For example, 
```javascript
let a = "3";
console.log(a); // SyntaxError: Unexpected token '.'
let b = ."4";
```
in this example, if there's no compilation phase, `console.log(a)` should work fine. However, as the error was found before execution phase, it return error.

#### Example
``` javascript
var name = 'zero';
function log() {
  console.log(name);
}

function wrapper() {
  var name = 'nero';
  log();
}
wrapper(); // zero
```
function `log`  scope was determined before execution. It is nested in global scope, not `wrapper`  scope. So, as `log` is executed as `wrapper` is executed, first, engine looks at variable `name` in funciton `log` scope. As it is not declared in it, engine looks at outer scope, which is global scope. That's why it returns `zero`.