0

Why is the declaration of the variable 'a' not used in the output of the console log of the below code? Doesn't that go against the scope chain? The variable 'a' with the undefined value on line 4 surely should be used on the console output on line 5?

var a = 15;
function checkScope(a) {
    var a;
    console.log(a); // log outputs 15 and not undefined
}

checkScope(a);

I want to understand this behaviour. To confirm, this behaviour has nothing to do with hoisting or even scope (i.e. scope chain)?

I don't believe scope is relevant to explain this behaviour because 'a' exists locally (its value is 'undefined' as it's not initialised) within the function, hence the Javascript engine will not look to the outer lexical environment to find 'a' (which has a value of 15). Or as per the MDN page: "The scope of a variable declared with var is its current execution context", which in this case is the enclosing function 'a'.

I also don't believe this behaviour is a result of hoisting as far as I know.

So, in addition, this is what is stated on the MDN page? "If you re-declare a JavaScript variable, it will not lose its value."?

  • Off-topic question but, what's the reason behind MDN's statement above? Is it simply related to memory management? There's no point to logical reason to allocate a new memory address every single time a variable is declared?

Now, going back to my question:

Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored? But I don't think so because both variable are declared in their own, separate execution contexts, so surely the variable 'a' in line 4 is being used/accessed? Because the scope chain would suggest that the closest local variable would be used (i.e. the local 'a' with a value of undefined), and in addition, I would best think that the MDN statement applies to only re-declared variables only within the same lexical environment, correct?

I am just trying to work out whether 'a' in line 4 is actually used when we refer to 'a' in line 5? Or is line 3 ignored, and thus line 5 will instead access (refer to) the 'a' in line 3 (i.e. checkScope's 'a' parameter)? - The latter sort of implies the former

It makes sense if line 3 from the above code is simply ignored, because deleting it achieves the same result:

var a = 15;

function checkScope(a) {
  console.log(a); // log outputs 15 and not undefined
}

checkScope(a);

Thanks.

151SoBad
  • 115
  • 9
  • If you had good linting from your IDE, you'd actually get a notice that `var a;` was redundant (inside the function). It was declared already in the function parameter as it came into function `checkScope(a)`. _That_ is where `a` is declared, _not_ in the `var a` inside the function. And, as you pass in `a` with a value of `15`, your note about the MDN "if you redeclare, it will not lose it's value" comes into play - `a` existed, it was `15`, regardless of the `var a;` inside the function. – random_user_name Sep 02 '17 at 13:59

4 Answers4

2

If you redeclare a JavaScript variable, it will not lose its value.

take a look at this answer.

var a = 15;

function checkScope(a) {
    var a; // this is equivalent to redeclaring the variable
    console.log(a); // log outputs 15 and not undefined
}

checkScope(a);
marvel308
  • 10,288
  • 1
  • 21
  • 32
2

Basically line 4

var a;

is where the compiler finds a redeclared variable of the function parameter. Because of the missing initializing, a keeps the value of the handed over value of the parameter a.

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Makes sense - thanks Nina. Re-declarations may be ignored, but if we initialise the local variable 'a' to say, for example, "foo", it is reassigned to that string, and then the console.log will output that string (instead of the number '15') because of the scope chain? (which would notice that a local variable 'a' exists?). Or does my entire question have absolutely nothing to do with the scope chain, as in my OP, the function parameter is basically the local variable that is being accessed in the console.log? – 151SoBad Sep 02 '17 at 14:19
  • Put simply, do function parameters have the same scope as variables locally declared and/or initialised in the body of that function? i.e. function parameters have function body scope? – 151SoBad Sep 02 '17 at 14:25
  • the declaring with inializing becomes just an assingment without (re)declaring in the same scope. scope of inner `a` is the function and ther the variable is declared in the parameter section. if you take `var a = 'foo';` the the `var` part (declaring) gets ignored, but the assingment happens. As result you get `a` with a value of `'foo'`. – Nina Scholz Sep 02 '17 at 14:25
  • ad2, not just the body, in the parameter, the variable is declared and working, too, like default values like `function checkScope(a, b = a) {`, where `b` gets the value of `a` if `b` is `undefined`. – Nina Scholz Sep 02 '17 at 14:28
  • Ah, I just wrote a reply and the page crashed. Put simply, thanks, that makes sense! I just read somewhere that function parameters have higher precedence than variable declarations. What does that mean? I thought it would apply here to my case, but when I changed the code in the OP to declare var ab = 20 within the checkScope function, and also named the function parameter as 'ab', I thought the 'function parameter has higher precedence over local variables' would mean console.log would output '15' (the value of the func parameter), and not 20 (value of local variable). Can you explain this? – 151SoBad Sep 02 '17 at 14:37
  • you get the value of the last assingment, in this case `20`. – Nina Scholz Sep 02 '17 at 14:42
2

You have declared a variable named a three times.

  • Once as a global on line 1: var a = 15;
  • Twice inside the function:
    • Once with a var statement on line 4: var a;
    • Once with an argument definition on line 3: function checkScope(a) {

The line 4 var has no effect. The variable is already declared.

Then you call checkScope(a); which passes the value of the global a (15) to the local a argument of checkScope. This is why it is 15 and not undefined.


Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored?

var a is basically ignored.

But I don't think so because both variable are declared in their own, separate execution contexts

This is where you are being tripped up by having three and not two declarations of a. It declares the variable defined by the function argument name.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Yeah I think the odd one is the argument definition, or formal parameter variable. It sort of implies func (var a) {}, yet we can't use the keyword var in the formal parameters, whereas in other programming languages, you can. That makes sense why you suggest line 4 var would have no effect, because it's basically a duplication/re-declaration of the already-implied 'var' declaration inside the formal parameters of checkScope, is that correct? – 151SoBad Sep 02 '17 at 14:06
0

Consider 'a' to be different assigned variable for arguments in function and inside as a local variable.

function a != var a;

Now, some 'a' is called by console.log(a). Now, it will search for the default 'a' value if existing, i.e, 'a' of function. Even on manipulation of 'a',

function hoist(a) {
      var a;
      a*=2;
      console.log(a);
}

hoist(10);

output: 20

Ank_247shbm
  • 512
  • 7
  • 17