The hidden scope of a named function expression
Tags: javascript, webdev, programming, ecmascript
Published: 2022-01-25 12:49:39

There are several syntaxes to create a function in JavaScript. One of them is called _function expression_:

```js
const f = function() {}
```

It is also possible to add a name inside function expression and such syntax is well known as _named function expression_:

```js
const f = function internal(){}
```

If a function is created like that then variable `internal` is available inside the function scope and is not available in the global scope:

```js
const f = function internal(){
console.log(internal)
}
f(); // f internal(){...}
internal; // Reference error internal is not defined
```

Ok cool, it is basic and looks pretty straightforward. But...

Where exactly is variable `internal` defined?

##First idea - function scope

Let's say that variable `internal` is defined in the function scope. It is a decent guess as we have just checked that the variable is accessible only inside the function scope and is not accessible in the global one. But what if we create a constant and name it `internal` inside the function body:

```js
const f = function internal(){
const internal = 100;
console.log(internal)
}
f();
// 100 in console
```

The code does not throw any errors and it seems that we have just created a constant with the name `internal` in the scope which already had variable `internal` (from function name) successfully. But the issue is that JS does not allow to use const statement with an identifier which has already been used in var/let/const statement earlier in the code. So there are two ways to avoid that issue. 

The first way is to assume that there is a special mechanism inside a function scope which controls creation and access to a variable instantiated from a function expression name (**false**). 
The second - to use something elegant and already existing (**true**).

##Second idea - intermediate scope

Actually there is only one way to get full and detailed information about JS internals. It is the [ECMAScript Language Specification](https://tc39.es/ecma262/). Definitely it is not an easy reading and it requires some experience, but believe me, it is worth investing your time in it.

But before checking a description of a named function expression in the spec let's refresh one famous JS term - **closure** (yeap, again)

So closure is a function with a scope where the function is created. Actually every function in JS is a closure.

```js
const b = 20
const f = function (){
const a = 10;
a;
b;
}
f()
```

When `function f` is <u>created</u> it "learns" the surrounding scope. When `function f` is <u>called</u> a local function scope is created and then chained to the outer scope the function remembered during its creation:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/01h1r510c7sf11rafqgp.jpg)

A variable identifier resolution starts from a local function scope (const a). If a variable is not found in the local scope (const b), the resolution is delegated to the outer scope (global scope in the example). That is how the scopes are chained to each other. Cool, easy!

Let's jump back to a named function expression. There is a [section](https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression) describing creation of a named function expression. 

There are key steps:

```
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }

2. Set name to StringValue of BindingIdentifier.
3. Let outerEnv be the running execution context's LexicalEnvironment.
4. Let funcEnv be NewDeclarativeEnvironment(outerEnv).
5. Perform funcEnv.CreateImmutableBinding(name, false).

8. Let closure be OrdinaryFunctionCreate(...).

11. Perform funcEnv.InitializeBinding(name, closure).
12. Return closure.
```

**<u>The main idea is to create an additional intermediate scope in a closure for keeping only one variable with a function name!</u>**

The following code example:

```js
const b = 20
const f = function internal(){
const a = 10;
a;
internal;
b;
}
f()
```

may be presented like that:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4pt8xfklgy8h50cdqlo.jpg)

So this is an answer to our initial question: "Where exactly is variable `internal` defined?"

The variable `internal` is not available in the global scope and at the same time it does not block creation of a variable with the same name inside a function scope because the `internal` lives in its own scope between the global and the function scope. Win-win! 

##Final part

Ok, now we know that variable `internal` has its own scope but is it constant or variable? May we reassign a different value to it? Let's try something like that:

```js
const f = function internal(){
internal = 100;
console.log(internal)
}
f()
```

The identifier `internal` still contains a function and there are no errors. This is actually interesting and I admit that such a logic is quite unique. 

According the spec, variable `internal` in our example is created via **_CreateImmutableBinding_** abstract method. 

That method is used to create constants but also has a boolean flag as a second argument. If that flag is `false` then a different value cannot be assigned to the identifier. However, such an assignment does not throw an error. In case of a constant statement that flag is `true` and a reassignment throws TypeError.