JavaScript TDZ and Variable Shadowing
By: Ashan Dhananjaya
Tags: Js, Programming, Functional Programming, Javascript Development, JavaScript

In this article we will see how the Temporal Dead Zone (TDZ) and Variable Shadowing effects in our day to day programming life which introduced with the ES6 in 2015. Temporal Dead Zone (TDZ) affect our coding when we declare variables with let and the care that the developer needs to take. Variable shadowing occurs when a variable is declared in certain scope has the same name defined on it’s outer scope. And when we call the variable from the inner scope, the value mentioned in inner scope will be taken into account.

Temporal Dead Zone

Declaration with var

Let’s look at the following example that declares a variable through var :

function mainFunc() {

alert(name);

var name = 'Jorden';

}

mainFunc();

As much as we have written code this way, when it is processed by a JavaScript engine it will be interpreted in this way:

function mainFunc() {

var name;

alert(name);

name = 'Jorden';

}

mainFunc();

What we have just seen is the hoisting (lifting) of the variable name to the beginning of the code block in which it was declared. Though, we have the declaration var name; , which has no attribution. So it alert(name) displays it undefined instead of an error claiming that the variable does not exist.

However, when we use it let , introduced from ES2015 (ES6) we need to be aware. Bearing in mind that variables declared with let have block scope and cannot be re-declared within the same scope.

Let statements

Variables declared as let are also hoisting (lifting). However, their access is only allowed after receiving an assignment; otherwise, we will have an error.

Let’s look at the previous example, this time using let :

function mainFunc() {

alert(name);

let name = 'Michael';

} mainFunc();

When we execute our code, we will receive the following error message:

Uncaught ReferenceError: Cannot access 'name' before initialization

As stated, variables declared with let are also hoisted, so our code will look like this when interpreted:

function mainFunc() {

let name;

alert(name);

name = 'Jackson';

} mainFunc();

But what explains this different behavior with variables declared with let ? That's what we'll see next. Between the declaration of the variable with let and its assignment there is the Temporal Dead Zone (TDZ) . Any access made to the variable in that time will result in ReferenceError . However, it is a beneficial error, as accessing a variable before assigning it is rarely intentional in an application.

Nothing prevents us from deliberately doing this:

function mainFunc() {

let name = undefined;

alert(name); //TDZ

name = 'Jackson';

} mainFunc();

The result of alert will be undefined . It makes perfect sense, because we access the variable name after receiving an assignment, that is, outside the Temporal Dead Zone.

Variables declared with const are not affected by TDZ , as they must be initialized during their declaration.

Variable Shadowing

Global scope and Local Scope

In JavaScript there are two types of scope. Lets check this example first,

let firstName = "Michael"

function mainFunc() {

let lastName = "Jackson";

console.log(lastName);

}

console.log(firstName); //Prints => Michael

mainFunc(); //Prints => Jackson

Local scope

Variables defined within a function are local variables. So in the above example lastName is defined in the function so it is also a local variable .

Global scope

Variables defined outside a function are called global variables.Variable firstName declared in the out of the function mainFunc() so we identify it as a global variable.

Shadowing

Lets jump into the variable shadowing. Assume if we declare both the variables using the same variable name,

let name = "Michael"

function mainFunc() {

let name = "Jackson";

console.log(name); //Prints => Jackson

}

console.log(name); //Prints => Michael

The variable declared in the local scope overrides the variable declared in the global scope this is why when we print the variable name inside the mainFunc() prints Jackson instead Michael this is variable shadowing. This helps to co-exist 2 variable with the same name variables, both be accessible but this not a good practice in programming.

Why is it a problem?

Since this condition has two consequences. Firstly, it blocks us from gaining access from the inner scope to the variable defined in the outer scope. Secondly, it prevents any changes or reassignments to the variable defined in the outer scope from within the inner scope. More importantly to remember though is that variable shadowing should be avoided. The reason is that it can obfuscate the intention and clarity of your program, which could potentially lead to hidden bugs and unintended results in programming.

So how can I avoid it?

Simply you can avoid variable shadowing by renaming these variables with a unique name such as firstName and lastName according to our example.