What Is the Correct Term for Variable Shadowing in JavaScript

What is the correct term for variable shadowing in JavaScript?

The correct term is [Variable] Shadowing

In computer programming, variable shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope. This outer variable is said to be shadowed...

Functions in JavaScript are just function-objects stored within variables (or properties) that follow the same scope-chain/resolution rules as normal variables (or properties). This explains why the original can still be accessed as window.parseInt as well. It is the "IIFE" which introduces this new scope (functions are the only way to introduce new scope in JavaScript).

However, the ECMAScript Specification [5th Edition] does not use the term shadowing, nor can I find a specific replacement term. (The fundamental shadowing behavior is defined in "10.2.2.1 GetIdentifierReference" and related sections.)

It is not overloading and it is not overriding, which are entirely different. I have no idea where overshadowing (in this context) originated or how it is supposed to differ from "normal" [variable] shadowing. If the term shadowing didn't already exist to explain this behavior then -- from an English language viewpoint anyway -- overshadowing ("to make insignificant/inconsequential") might be more appropriate than shadowing ("to cast shadow on/darken").

Happy coding.

Trying to understand better variable shadowing

Firstly, you need to understand that you have 2 scopes here one is global and other is functional.
Imagine scope as a object to which each variable defined within it, is attached as a property. Here function scope is nested within global.

Now variable lookup starts from running scope(context). If variable is not present over there it will keep on looking into outer scopes (not inner) until it finds variable or reach global scope

Now case 1:

let a = 10;             //[[globalScope]] = {a: 10}
function increase1(a){ //[[increase1Scope]] = {a : 10} as parameters are local variable to function
a++; } //[[increase1Scope]] = {a: 11}
increase1(a); //here u have passed 10 as a **value** to increase1 param a(you havent passed global variable **"a"** but its value)
console.log('a = ',a); //takes value from its running scope i.e [[globalScope]] which is 10

case 2:

let a = 10;            //[[globalScope]] = {a: 10}
function increase2(){ //no parameters so [[increase2Scope]] = {}
a++;} //[[increase2Scope]] don't have a, so look into next outerscope i.e. [[globalScope]] and alter its value to [[globalScope]] = {a: 11}
increase2(a); //as increase2() has no defined parameter so this argument of 10 wont do anything
console.log('a = ',a); //same from [[globalScope]] = {a: 11}

case 3:

let a = 10;             //[[globalScope]] = {a: 10}
function increase3(x){ //[[increase1Scope]] = {x: 10}
x++; } //[[increase1Scope]] = {x: 11}
increase3(a); //value 10 get passed to increase3 -> x
console.log('a = ',a); //this time [[globalScope]] = {a: 10}, so 10

Now, As increase3() function is not returning anything, so you are getting undefined

console.log('a = ',increase3(a));  //undefined

To get the desired result, include a return statement in function definition:

function increase3(x){  
x++;
return x;
}

Hope it will help. I tried to put something into perspective.
I highly recommend you to go through below online JS book. It will certainly help.

https://javascript.info/closure

Javascript - variable re-delcaring in the sub-block // Variable Shadowing

I believe I found the answer here:

Demystifying JavaScript Variable Scope and Hoisting

In JavaScript, variables with the same name can be specified at
multiple layers of nested scope. In such case local variables gain
priority over global variables. If you declare a local variable and a
global variable with the same name, the local variable will take
precedence when you use it inside a function. This type of behavior is
called shadowing. Simply put, the inner variable shadows the outer.

and here as well:

https://stackoverflow.com/a/11901489/6375464

In computer programming, variable shadowing occurs when a variable
declared within a certain scope (decision block, method, or inner
class) has the same name as a variable declared in an outer scope.
This outer variable is said to be shadowed...

Is there a way to access a shadowed variable in JavaScript?

As-written?
No.

If you're not dead-set on naming each one a, then you can easily reference it.
The other solution would be to capture the outside variable within another variable, the trick being to not have the same variable name being referenced in the outside scope, from the inside scope.

window.a = 1;
function x() {
var a = 2,
inner_a = a,

y = function () {
var old_a = inner_a,
// a is equal to the closest var assignment ie: inside x()
a = 3;
};
}

or to pass it into the construction of a new function through closure

(immediately-invoking function)

window.a = 1;
function x() {
var a = 2;
var y = (function (old_a) {
return function () { var a = 3; };
// this inner function has access to "old_a", through closure
}(a));
}

This is a pattern that is preferred for several use-cases, when mixing JS with browser-functionality (ie: the DOM and DOM events, loops which assign timers or callbacks, AJAX responses, et cetera).

Can a function argument shadow a global variable

That is correct; the global variable is being shadowed. Think about it. In this statement:

myvar = myvar;

if there was no shadowing, which myvar would be the global one and which the local one?

Is it bad practice to shadow variables of a callback?

Matter of opinion, but I'd say yes - bad practice. In any case, there are two problems here

  • It can be confusing for the next person (which could be you) who needs to work on this code.

  • At some future time, you may need to access the outer values to provide some new functionalities (for example, want to make sure the two file objects have the same type?). Making that change will require an annoying and error-prone edit of the entire code block.

Use different names now to prevent problems later.

const and let variable shadowing in a switch statement

Hoisting and Temporal Dead Zone!

let and const get hoisted to the nearest block, so it becomes something like this:

switch (check) {
let productId;
case false:
console.log(productId);
break;
case true:
productId = 2;
console.log(productId);
break;
}

and thus because of temporal dead zone, the ReferenceError comes up

Making Sense of 'No Shadowed Variable' tslint Warning

The linter complains because you are redefining the same variable multiple times. Thus replacing the ones in the closure containing it.

Instead of redeclaring it just use it:

private getNextStageStep(currentDisciplineSelected) {
let nextStageStep = '';
if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 1') {
nextStageStep = 'step 2';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 2') {
nextStageStep = 'step 3';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 3') {
nextStageStep = 'step 4';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 4') {
nextStageStep = 'step 5';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 5') {
nextStageStep = 'step 6';
}
return nextStageStep;
}


Related Topics



Leave a reply



Submit