After reading recent posts for newbies to JavaScript, I decided to write a small topic about one interesting question that none of the authors have yet touched, namely, the question about the scope of functions in JavaScript.
As Wikipedia says: ECMAScript functions have lexical scope. This means that the scope is determined at the time the function is defined (as opposed to the dynamic scope, in which the scope is determined at the time the function is called).
Actually, everything is written quite briefly and clearly, but let's analyze in practice such an example:
var y = 5; var x = function(){ return y; }; var z = function(t){ var y = 10; return t(); }; z(x);
I will not try your patience, as a result we will get the number 5, although it is possible for some readers this result will be unexpected. Let's see what is the matter, but first a small lyrical digression.
In JavaScript, all functions are closures (lexical closures). This means that the function is not just a fragment of executable code, but also the context in which this fragment will be executed. In JavaScript, this context is a kind of chain. The first link in the chain is the function call object, which includes all local variables, and the object reference in the context of which the function was
declared , in turn, this object can refer to the parent object (if the higher function is declared inside another function), and so Further. To make it easier to understand what it is about, I will give an excellent illustration (taken
from here )
')

In the picture you can see how the variables will be searched. It looks like this: z is a local variable of the function, it will be found directly in the call object, x is not in the call object, so the search will be done higher up the chain. The search for variables is performed up to the global object, if the variable in it is not found, the result will be the value undefined.
So, now we are ready to analyze the first example in detail.
I read the example again and realized that I still did not understand anything. What is going on here? As mentioned above, functions in JavaScript are closures, that is, they store the context in which they were declared. Thus, keeping the function in a variable, we involuntarily save the context in which it was declared, and it in turn is a chain of a call object containing local variables and from a global object standing in the chain to a higher level.
There is one subtlety. The context (chain of scopes) in which the function was declared is roughly a chain of
objects . This is very important to understand, since objects in JavaScript are stored as links, that is, each element of the chain refers to a specific object (it refers to and does not contain its copy), which may change during the execution of the program. That is, an object from the scope chain can be changed by some external functions, while all changes will be available and, as part of the function, the changeable object is included in whose chain of scope. In other words, the chain of scopes is fixed at the moment of defining the function, but the list of properties defined in this chain is not fixed. The scope chain is subject to change, and the function can access all elements that exist at the time of execution. This is a very important paragraph, if you are not sure that you understood it exactly, read it again. Once you realize everything written in it, you will open the door to creating powerful effects, which are usually called
closures .
Thus, at the moment when we try to execute the function x (), the following will happen - the JavaScript interpreter will try to find a variable with the name y in the call object, does not find it, and switches to searching in the global object. In the global object, a variable with the name y exists, since we declared it right before the function declaration.
Since the chain of scopes of the function x is already fixed, the values of the local variables of the function z, inside which x () eventually starts, are still not used, since when executing the function x (), the variables will be searched within the scope of the fixed at the time of the announcement functions.
Instead of conclusions: I hope the example described above clearly demonstrates what a lexical scope is and how it differs from a dynamic one.
In order to make sure that you realize the beauty of closures and understand what the lexical scope of functions is, consider another small example:
var y = 5; var x = function(){ return y; }; var z = function(t){ var y = 10; return t(); }; y = 15; z(x);
PS In the comments, the respected haje-user
jeje gives an interesting example, which is also worth considering:
var y = 5; var x = function(){ return y; }; var z = function(t){ y = 10;
This example differs from the original one in that inside the z () function the variable
y is used without the keyword var. As a result of this example, we get the output number 10. Why is this happening? In fact, we have already answered this question, this happens because inside the function z () we no longer declare a local variable
y , but refer to the global one.
This example raises a very important question - the question of implicitly declaring variables in JavaScript. When inside a function we use a variable without the var keyword, the interpreter performs the following operations: A search is performed on the call object (local variable search), if the variable is not found, the search is performed on the object located higher in the chain of visibility and so on up to the global object. If a variable is found in any object, its value will be changed, so access to global variables is provided. There is only one BUT: if the variable is not found in any object in the chain of scopes, the JavaScript interpreter will automatically declare the variable being used and assign it to the variable, and the variable will be created in the
global scope. Given this, special attention should be paid to the function variables used without the var keyword. There are other interesting features to the explicit and implicit declaration of variables, but this is a topic for another micro-topic.