JavaScript Lexical Scoping and Nested Functions
Tags: javascript, webdev, codenewbie, beginners
Published: 2023-10-24 05:50:43

Nested functions are functions defined within the body of another function. In JavaScript, when you declare a function inside another function, the inner function has access to the variables and parameters of its containing (outer) function. This ability of the inner function to access the variables of the outer function, even after the outer function has completed execution, is what creates a [closure](https://dev.to/tanmaycode/closures-in-javascript-4f6k).

Here's how nested functions work and how the inner function closes over the variables from the outer function's scope:

A. **Defining a Nested Function**
```js
function outer() {
  let outerVar = 10;

  function inner() {
    console.log(outerVar);
  }

  return inner;
}

```
In this example, `inner` is a function defined inside the `outer` function.

B. **Accessing Outer Variables:**
The inner function, in this case, `inner()`, has access to all the variables and parameters of its containing scope, which is the `outer()` function. This includes `outerVar`, which is a variable declared in `outer()`.

C. **Closure Creation:**
When the `outer` function is executed, it defines `inner()` but doesn't execute it immediately. Instead, it returns the `inner` function itself. This means `inner` is a closure because it "closes over" or retains a reference to the `outerVar` variable from the `outer` function's scope.

D. **Accessing Outer Variables Later:**
Even after the `outer` function has completed execution and its scope should technically have exited, the `inner` function still has access to `outerVar`. You can call `inner()` at any time, and it will log the value of `outerVar` because it remembers the reference to it.
    

Here's how you would use the nested functions and the closure:
```js
const closureFunc = outer(); // outer() returns inner()
closureFunc(); // This logs the value of outerVar (which is 10)

```

When `closureFunc()` is called, it executes `inner()`, which can still access `outerVar` because of the closure. This is a fundamental feature of #closures in JavaScript, allowing you to create private variables and functions within the scope of an outer function and use them later as needed.


An example of the nested function and closures

```js
function outerfunction(){

let pop="pop-up1"

function dance(){

let pop="pop-up-z"

console.log(pop)

function sing(){

console.log(pop)

}

pop="pop-up-y"

sing()

}

pop="pop-up2"

console.log(pop)

return dance

}

let z = outerfunction()

z()

//console output:

//pop-up2

//pop-up-z

//pop-up-y
```

Now let us see what is happening here.
- outerfunction() will call the function, this will initialize the pop variable and then update it to pop-up2 and then log this value in console.
- Then this function returns another function which is dance, stored in the variable z, when z() calls happens the dance function will be called.
- when dance function is called, it creates a variable pop with value pop-up-z and then console log happens which log this value to console and the it changes the value of pop variable to pop-up-y and then it calls the function sing()
- when sing function is called, it console log the value of pop from its lexical environment, which is the pop-up-y. 

*notice here all the nested functions are accessing the variable from their lexical (nearest) environment which is also an example of #lexicalScoping*