let a = 'global'; function outer() { let b = 'outer'; function inner() { let c = 'inner' console.log(c); // 'inner' console.log(b); // 'outer' console.log(a); // 'global' } console.log(a); // 'global' console.log(b); // 'outer' inner(); } outer(); console.log(a); // 'global'
inner()
function has access to variables declared in its own scope, in the scope of the outer()
function, and in the global scope. The outer()
function has access to variables declared in its own scope and global scope. Global { outer { inner } }
inner()
function is surrounded by the lexical environment of the outer()
function, which, in turn, is surrounded by the global scope. That is why the inner()
function can access variables declared in the outer()
function and in the global scope. function person() { let name = 'Peter'; return function displayName() { console.log(name); }; } let peter = person(); peter(); // 'Peter'
person()
function, which returns the internal displayName()
function, and store this function in the peter
variable. When we then call the peter()
function (the corresponding variable actually stores the reference to the displayName()
function), the name Peter
is displayed in the console.displayName()
function does not have a variable named name
, so we can conclude that this function can somehow access the variable declared in the function external to it, person()
, even after how this function worked. Perhaps this is because the displayName()
function is actually a closure. function getCounter() { let counter = 0; return function() { return counter++; } } let count = getCounter(); console.log(count()); // 0 console.log(count()); // 1 console.log(count()); // 2
getCounter()
function in the variable count
. Since the count()
function is a closure, it can access the counter
variable of the getCount()
function even after the getCounter()
function has completed its work.counter
variable is not reset to 0 each time the count()
function is called. It may seem that it should be reset to 0, as it could be when calling a normal function, but this does not happen.count()
function is called, a new scope is created for it, but there is only one scope for the getCounter()
function. Since the counter
variable is declared in the scope of the getCounter()
function, its value between count()
function calls is preserved, not resetting to 0.first()
, it creates a new execution context for this function and places it on top of the stack.first()
function is completed, its execution context is retrieved from the call stack and control is transferred to the execution context that is below it, that is, the global context. After that, the code remaining in the global scope will be executed. lexicalEnvironment = { environmentRecord: { <identifier> : <value>, <identifier> : <value> } outer: < Reference to the parent lexical environment> }
let a = 'Hello World!'; function first() { let b = 25; console.log('Inside first function'); } first(); console.log('Inside global execution context');
globalLexicalEnvironment = { environmentRecord: { a : 'Hello World!', first : < reference to function object > } outer: null }
outer
) is set to null
, since the global scope does not have an external lexical environment.first()
function, it also creates a lexical environment for storing variables declared in this function during its execution. As a result, the lexical environment of the function will look like this: functionLexicalEnvironment = { environmentRecord: { b : 25, } outer: <globalLexicalEnvironment> }
<globalLexicalEnvironment>
, since in the source code the function code is in the global scope. function person() { let name = 'Peter'; return function displayName() { console.log(name); }; } let peter = person(); peter(); // 'Peter'
person()
function is executed, the JS engine creates a new execution context and a new lexical environment for this function. Completing the work, the function returns the displayName()
function, a reference to this function is written to the peter
variable. personLexicalEnvironment = { environmentRecord: { name : 'Peter', displayName: < displayName function reference> } outer: <globalLexicalEnvironment> }
person()
function completes, its execution context is retrieved from the stack. But its lexical environment remains in memory, since the link to it is in the lexical environment of its internal function displayName()
. As a result, variables declared in this lexical environment remain accessible.peter()
function is called (the corresponding variable stores a reference to the displayName()
function), the JS engine creates a new execution context and a new lexical environment for this function. This lexical environment will look like this: displayNameLexicalEnvironment = { environmentRecord: { } outer: <personLexicalEnvironment> }
displayName()
function has no variables, so its environment record will be empty. During the execution of this function, the JS engine will try to find the name
variable in the lexical environment of the function.displayName()
function cannot be found in the lexical environment, the search will continue in the external lexical environment, that is, in the lexical environment of the person()
function, which is still in memory. There, the engine finds the desired variable and displays its value in the console. function getCounter() { let counter = 0; return function() { return counter++; } } let count = getCounter(); console.log(count()); // 0 console.log(count()); // 1 console.log(count()); // 2
getCounter()
function will look like this: getCounterLexicalEnvironment = { environmentRecord: { counter: 0, <anonymous function> : < reference to function> } outer: <globalLexicalEnvironment> }
count
.count()
function is executed, its lexical environment looks like this: countLexicalEnvironment = { environmentRecord: { } outer: <getCountLexicalEnvironment> }
counter
variable in its lexical environment. In this case, again, the record of the function environment is empty, so the search for the variable continues in the external lexical environment of the function.counter
variable stored in the getCounter()
function's lexical environment.getCounter()
function after the first call of the count()
function will look like this: getCounterLexicalEnvironment = { environmentRecord: { counter: 1, <anonymous function> : < reference to function> } outer: <globalLexicalEnvironment> }
count()
function, the JavaScript engine creates a new lexical environment for this function and increments the counter
variable, which leads to changes in the lexical environment of the getCounter()
function.Source: https://habr.com/ru/post/424967/
All Articles