Skip to main content

Variable Scope / Closures

Advanced Functions: Variable Scope / Closures

What are the three types of variable declarations in JavaScript?

View Answer:
Interview Response: There are three types of variable declarations in JavaScript, including let, const, and the var legacy variable.

Code Example: Declaration

let arr = [1, 2, 3];

const str = 'Hello';

var num = 1;

What is a code block or block statement (compound statement) in JavaScript?

View Answer:
Interview Response: We can use a block statement or compound statement to group zero or more statements encapsulated in curly brackets.

Code Example: Code Block

// do some job with local variables that should not be seen outside
{
let message = 'Hello'; // only visible in this block

alert(message); // Hello
}

alert(message); // Error: message is not defined

// We can use this to isolate a piece of code
{
// show message
let message = 'Hello';
alert(message); // returns Hello
}

{
// show another message
let message = 'Goodbye';
alert(message); // returns Goodbye
}

What are the benefits of a JavaScript code block or block statement?

View Answer:
Interview Response: The main benefit is isolating a portion of your code, which improves control and reduces errors in your application.

Code Example: No code block control results in an error

// show message
let message = 'Hello';
alert(message);

// show another message
let message = 'Goodbye'; // Error: variable already declared
alert(message);

Does JavaScript support nested functions? How do they work?

View Answer:
Interview Response: Yes, nested functions have interesting scoping rules in JavaScript. A nested function can access any variables and parameters of their outer parent function(s). This behavior allows us to give the parent function additional dynamic features.

Code Example:

function sayHiBye(firstName, lastName) {
// helper nested function to use below
function getFullName() {
return firstName + ' ' + lastName;
}

alert('Hello, ' + getFullName());
alert('Bye, ' + getFullName());
}
note

Nested functions are pretty standard in JavaScript because of their dynamic abilities, which allow an extension of the originating function.


Can you explain what is the Lexical Environment is in JavaScript?

View Answer:
Interview Response: The Lexical Environment is a theoretical specification object, and it gets used to describe how things work. The Lexical Environment object consists of two parts, including the environment record and a reference to the outer lexical environment.

Technical Response: "Lexical Environment" is a specification object: it only exists "theoretically" in the language specification to describe how things work. We cannot access this object in our code and manipulate it directly. JavaScript engines may also optimize it, discard unused variables to save memory, and perform other internal tricks if the visible behavior remains as described. The Lexical Environment object consists of two parts, including the environment record and a reference to the outer lexical environment. The Environment Record is an object that stores local variables as its properties (and some other information like the value of this).


note

The Environment Record is an object that stores all local variables as its properties and some other information like the value of this.


Can you explain how a variable works in the context of a JavaScript engine?

View Answer:
Interview Response: A variable is just a property of the special internal object called the Environment Record. To access or change a variable means to get or manipulate a property of that object.

Code Example:

let word = 'Hello';
// Lexical Environment Record --> property = word: "Hello"; outer --> null

// ENGINE EXECUTION

// execution start --> word: <uninitialized> - outer --> null
let word; // word: undefined
word = 'Hello'; // word: "Hello"

What is the distinction between a function declaration and a variable declaration?

View Answer:
Interview Response: A function is also a value, like a variable. The difference is that a Function Declaration is fully initialized when the script loads. When a Lexical Environment gets created, a Function Declaration immediately becomes a ready-to-use function.

note

You should be aware that this only applies to function declarations, not function expressions.


In JavaScript, what is a closure?

View Answer:
Interview Response: A closure is a function that remembers its outer variables and can access them. In JavaScript, all functions are naturally Closures (there is only one exception, The "new Function" syntax). Functions automatically remember where their point of creation is using a hidden [[Environment]] property, and then their code can access outer variables.

Technical Response: A closure is a function that remembers its outer variables and can access them. In some languages, that is impossible, or a function is written in a special way to make it happen. In JavaScript, all functions are naturally Closures (there is only one exception, The "new Function" syntax). Functions automatically remember where their point of creation is using a hidden [[Environment]] property, and then their code can access outer variables.

note

This should not be confused with a code block.


How does garbage collection work with the Lexical Environment and nested functions in JavaScript?

View Answer:
Interview Response: Usually, a Lexical Environment is removed from memory with all the variables after the function call finishes. That is because there are no references to it. As with any JavaScript object, it is only kept in memory while it is reachable. A Lexical Environment object dies when it becomes unreachable (like any other object). In other words, it exists while there is at least one nested function referencing it.

Technical Response: After the function call completes, a Lexical Environment typically disappears from memory and all variables. This behavior occurs because there are no references to it, and it is only retained in memory while it is accessible, just like any other JavaScript object. If a nested function is reached after the end of a function, it contains the [[Environment]] attribute, which refers to the lexical environment. In such a situation, the Lexical Environment is still available even after the function completes, therefore, it remains alive. When a Lexical Environment object becomes inaccessible, it dies (like any other object). In other words, it persists as long as there is at least one nested function that refers to it.

Code Example:

function f() {
let value = 123;

return function () {
alert(value);
};
}

let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
// of the corresponding f() call

function f() {
let value = 123;

return function () {
alert(value);
};
}

let g = f(); // while g function exists, the value stays in memory

g = null; // ...and now the memory is cleaned up