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
Convert String in Dot Notation to Get the Object Reference
How to Convert Blob to File in JavaScript
Dangerous Implications of Allman Style in JavaScript
How to Extend Function with Es6 Classes
Uncaught Typeerror: Illegal Invocation in JavaScript
Precise Financial Calculation in JavaScript. What Are the Gotchas
Es6 Array Destructuring Weirdness
Check If a Value Is Within a Range of Numbers
JavaScript - How to Detect If Document Has Loaded (Ie 7/Firefox 3)
Returning Chrome Storage API Value Without Function
Checking If Jquery Is Loaded Using JavaScript
String.Replace' Weird Behavior When Using Dollar Sign ($) as Replacement
How to Remove All Listeners in an Element