Is This an Example of Variable Shadowing in JavaScript

understanding variable shadowing in javascript?

Usually, yes, variables declared later (with var) will simply overwrite vars declared earlier with the same name. The difference is that variables declared with var on the top level assign to window properties, and window.crypto is a property with a getter, but no setter:

console.log(  Object.getOwnPropertyDescriptor(window, 'crypto'));

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

Illegal Shadowing (Shadowing let with var)

But why this is not valid in first case?

Because both of those declarations are in the same scope.¹ Your second example works because the let is scoped only to the block, not to the scope outside the block where var a exists. (Just like a local variable in a function.) So in the second example, it's shadowing. In the first example, it wouldn't be shadowing, it would be duplication, which you can't do with let (even if the other declaration uses var). (You can use var to declare a variable more than once in the same scope. The subsequent vars are ignored, though any initializer on the variable is converted to an assignment. E.g., var a; var a = 42; is identical to var a; a = 42;)


¹ Okay, so technically, it's a bit more complicated than that. var variables exist in an "outer" global lexical environment that holds bindings (loosely, variables) on the global object, but let variables exist on an "inner" global lexical environment that doesn't hold its bindings on the global object. Global scope is still just one scope, so as you've seen you can't have var a and let a both at global scope because they conflict with each other. But there are other ways to create "outer" global variables, such as assigning to a property on window (or this at global scope, or globalThis in modern environments):

// At global scope
window.a = 42; // Creates binding in the outer global environment
console.log(a); // Shows 42

which means it's possible to create a binding in both the outer and inner global lexical environments:

// At global scope
window.a = 42; // Creates binding in the outer global environment
let a = "answer"; // Creates binding in the inner global environment
console.log(a); // Shows "answer"

Since the inner one is closer to the code doing the console.log(a), the above outputs "answer".

Fun fact: Depending on how you count, on browsers there are somewhere between two and six layers to "the" global environment./p>

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.

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...

What is Shadow Identifier Declaration in JavaScript?

It's when you declare an identifier in a scope that hides one that exists in the containing scope:

var foo; // The outer one
function example() {
var foo; // The inner one -- this "shadows" the outer one, making the
// outer one inaccessible within this function
// ...
}

There are several ways you might shadow something:

  1. With a variable declaration (var, let, const), as above

  2. With a parameter declaration:

    var foo; // The outer one
    function example(foo) { // This parameter shadows the outer `foo`
    // ...
    }
  3. With a function declaration:

    var foo; // The outer one
    function example() {
    function foo() { // This shadows the outer `foo`
    }
    // ...
    }

...and several others. Anything that declares an identifier within a scope that hides (shadows) one in the containing scope, that's a shadowing declaration/definition.

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.

Variable shadowing and testing for existence before assignment in javascript

You're looking for x in the wrong scope. Due to variable hoisting, var x has actually defined a local x variable with a value of undefined before your x || 3 check happens:

var x = x || 3;

is actually:

var x = undefined;
x = x || 3;

Simply change it to look for x on the window object:

var x = window.x || 3;


Related Topics



Leave a reply



Submit