# JavaScript Function Closures and Scope: 
How Best To Leverage Closure in JavaScript.

## What is Closure in JavaScript?

In JavaScript, closures refer to the combination of a function and the lexical environment in which that function was declared. A closure is a function that references variables in the outer scope from its inner scope.

A [closure](https://www.w3schools.com/js/js_function_closures.asp) is created, every time a function is declared. What does this mean, and how best can we leverage closure in JavaScript? What does a closure look like? What is the value and impact of the closure on our code?

To understand how to leverage closure in our code in JavaScript, firstly we have to understand what scope is in JavaScript and how it is used.

### What is Scope?

In JavaScript, [scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope) determines how variables in JavaScript are accessed. The scope is created when you run a function in JavaScript and this creates a new runtime scope. This describes the set of variables which are referred to as identifiers, that are available for that function to use. Scope in JavaScript determines the accessibility of variables, objects, and functions from different parts of the code.

### Application of Scope in JavaScript.

There are three main types of scopes in JavaScript. But before ES6 (2015), JavaScript has only function scope and global scope but with the introduction of ES6 came new keywords like <mark>let </mark> and <mark>const</mark>. These new keywords <mark> let</mark> and <mark>const</mark> provide the block scope in JavaScript.

### Four areas of scopes in JavaScript

Function scope

Local Scope

Global scope

Block Scope

### Function Scope

In JavaScript, each function creates a new scope when variables are declared inside a function. This variable declared inside a function scope cannot be accessed from outside the function. Each function creates a new scope in a function declaration. The variables declared with <mark>var</mark>, <mark>let</mark> and <mark>const</mark> can have a function scope when declared inside a function.

### Examples of function scope declaration

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1676851340057/721b7923-59e2-4d98-b439-95699ba28e04.png align="center")

### Local scope Variable

Local scope variables have function scope.

When a variable is declared within a JavaScript function it becomes local to the function it is declared within and can only be accessed from within this function. This makes it possible to use variables with the same name in different functions because local variables are only recognized inside their function.

When is a local variable in the function scope created? Local variables are created at the start of a function and ceased to exist anymore once the function does not exist anymore or is completed.

### Examples of a local scope

```javascript
// code here cannot use the local scope variable
function myPet() {
    //local scope variable
  let petName = "Manny";
  console.log(petName)
}
myPet(); // Output Manny
```

### Global Scope Variable

In Javascript, the global scope variable is declared outside the javascript function, basically at the top of the function declaration. Global scope variables can be accessed anywhere in JavaScript.

### Examples of global scope variables

The variable keywords var, let, and const can be declared in the global scope. <mark>var x = 3;</mark> <mark>let x = 3;</mark> <mark>const x = 3;</mark>

```javascript
//Global scope variable
let man = "John";
function myGender(){
    //local scope variable
    let gender = "Male";
    console.log(gender + " " + man);
}
myGender(); //Output of the local variable: Male John
//console.log(gender + " " + man); // will give ReferenceError: gender is not defined
```

**Other methods of accessing global scope variables**

**Method 1**

<mark>Assigning a global scope variable when the value of a global variable can be changed inside a function.</mark>

```javascript
// The global variable scope can be changed inside the function
let carName = "Nissan";
function autoName(){
    carName = "Toyota";
}
//before the function call
console.log(carName); //Nissan
//the value of carName changes after the function call
autoName(); // Nissan
console.log(carName); //Toyota
```

**Method 2. Automatically global scope variable**

In JavaScript, a variable can become a global scope variable if a value is assigned to a variable that is not yet declared. The value is used without declaring it. It automatically becomes a global variable. The example below shows a value that is declared inside a function without a keyword variable. It automatically becomes a global variable.

```javascript
function greet() {
//global scope
    hello = "My World"
}
greet();
console.log(hello); //output My World
//This becomes a global scope as the value of the variable is declared with the let keyword. 
// if the value is declared with let hello = "My World"., it will throw an error.
```

## LEXICAL SCOPING

In block Scope, the scope variable can only be accessed in the immediate block. It can only be accessed inside the if statement block. The third console trying to access the blocked scope variable outside the block will throw an error.

```javascript
//global scope
let myName = "Emmy";
function familyName(){
    //local scope
    let fullName = "Nothingale";
    console.log(myName + " " + fullName);
}
familyName(); // Emmy Nothingale
```

The variable <mark>myName</mark> is a <mark>global scope variable</mark> that is accessible from anywhere including within the <mark>familyName() </mark> function.

The variable <mark> myName</mark> changes after the function call.

The variable <mark>fullName</mark> is a l<mark>ocal scope variable</mark> that is accessible only within the <mark>familyName()</mark>.

To access the <mark>fullName variable</mark> outside the <mark>familyName() function</mark> will throw an error.

### Nesting in Lexical Scoping

Mastering the concept of scoping functions and lexical scoping helps you understand the application of javascript closures.

In lexical scoping, the scopes can be nested and the inner function can access the variables declared. Nesting in lexical scoping comes with the parent and child function, the child function nested inside the parent function.

```javascript
function greetings() {
    let morning = "Good morning";
    function sayHello() {
        console.log(morning);
    }
    sayHi();
}
greeting(); // Good morning
```

The <mark>greetings() function</mark> is the <mark>parent function</mark> that creates a local variable <mark>let morning</mark>

The <mark>child function</mark> is the <mark>sayHello() function</mark> nested inside the <mark>greetings() function.</mark>

The child function <mark>sayHello()</mark> is accessible from within the body of the <mark>greetings() function</mark>.

The <mark>sayHello() function </mark> accesses the variables of the outer function message variable of the <mark>greetings() function</mark>.

### Nesting with a return function

In Javascript, you can return a function from another function. The nesting of the child function within the parent function returns another function.

```javascript
function morningGreeting() {
    let morning = "Good morning Manny";
    function sayHi() {
        console.log(morning);
    }
    return sayHi();
}
let hi = morningGreeting();  // Good morning Manny                                                                                                                                  
```

The <mark>greeting() function</mark> returns the <mark>sayHi() function</mark> that is nested inside it and acts as the holder of the entire function.

### Advanced Closure Application

```javascript
function todayGreeting(days) {
    return function(week) {
        return days + " " + week;
    } 
}
let weekday = todayGreeting('today');
let monthly = todayGreeting('month');
console.log(weekday('monday'));
console.log(monthly('January'));
```

The <mark>todayGreeting() function</mark> takes one argument <mark>"days"</mark> and returns a function that accepts a single argument named <mark>"month".</mark>

The return function returns a combination of days and week variables, the <mark>todayGreeting() function</mark> behaves like a holder function for the entire closure that creates <mark>weekday() </mark> and <mark>monthly()</mark> with respective messages.

The <mark>weekday()</mark> and <mark>monthly() </mark> are <mark>closures</mark> and they share the same function body but different scopes. In the weekday() closure, the message is today while in the monthly() closure the message is in January.

### Block scope nested inside global scope variable

```javascript
//global scope
let firstName = "Johnson"
function genderName() {
    //local scope variable
    let middleName = "Tony";
    console.log( firstName + " " + middleName);
    if (middleName == "Tony") {
        //block scope variable
        let familyName = "Owusu";
        console.log(firstName + " " + middleName + " " + familyName);
    }
    // variable c cannot be accessed here
    console.log(firstName + " " + middleName + " " + familyName);
}
genderName(); // Johnson Tony Owusu
```

The block scope named <mark>let familyName</mark> is declared inside the if statement block and can only be accessed inside the if statement block.

To study more on JavaScript scopes and closures check out these study materials[: w3chool JavaScript Scope](https://www.w3schools.com/js/js_scope.asp) and [MDN Scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope)
