In this article, we will learn about Variable Masking which is also known as Variable Shadowing i.e. a variable with the same name will shadow the variable in the outer scope. When a variable is masked, the masked variable is completely inaccessible using that variable name. The scope is hierarchical thus we can enter new scope without hampering the old one.
Where can it occur?
- Methods or Functions.
- Callback Functions.
- Block Scope.
Note: It can prevent any changes or reassignments to the variables defined in the outer scope from within the inner scope.
Example 1:
Javascript
{ // block 1 const x = 'Hi' ; console.log(x); // logs "Hi" } // logs "undefined" as x is out of scope console.log( typeof x); { // block 2 const x = 1; console.log(x); // logs "1" } // logs "undefined" as x is out of scope console.log( typeof x); |
Output:
Example 2: Now, we will observe what happens when we have nested scopes:
Javascript
{ // outer block let x = 'Hi' ; console.log(x); // logs "Hi" { // inner block let x = 1; console.log(x); // logs "1" } console.log(x); // logs "Hi" } // logs "undefined" as x is out of scope console.log( typeof x); |
Output:
Explanation: In the inner block, variable x is distinct from the outer block with the same name.It masks(hides) the x that’s defined in the outer scope. When execution enters the inner block, we have no way of accessing the variable in the outer scope as it has the same name! A new variable x is defined with variables in scope. Here is another example where x came into the scope and then exited scope before the second variable named x did the same.
Example:
Javascript
{ // outer block let x = { color: "blue" }; let y = x; // y and x refer to the same object let z = 3; { // inner block let x = 5; // outer x now masked console.log(x); // logs 5 console.log(y.color); // logs "blue"; // object pointed to by // y (and x in the outer scope) is // still in scope y.color = "red" ; console.log(z); // logs 3; z has not been masked } // logs "red"; object modified in inner scope console.log(x.color); // logs "red"; x and y point to the same object console.log(y.color); console.log(z); // logs 3 } |
Output:
Note: Variable masking should be avoided as it can disturb the intention and clarity of the program, which could lead to hidden bugs and unintended results.
How should we avoid it: Variable masking(shadowing) can be avoided by renaming the variable’s unambiguous names.
Example:
Javascript
let girl = 'Radha' ; [ 'Ram' , 'Raj' , 'Ramesh' ].forEach(boy => { //variable 'girl' defined is accessible in the inner scope. // Radha Radha Radha (repeated three times in each loop) console.log(girl); // Ram Raj Ramesh console.log(boy); }); |
Output:
This concludes that it is the practice of naming two variables( a global and local variable/local variable and a callback function parameter) with the same name which coexists in a scope where these variables are accessible. The scope chain determines what variables are in scope: all variables in the current scope chain are in scope, and (as long as they’re not masked), can be accessed.