Variables with the same name, but the local scope

2020-02-07 11:15发布

问题:

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.

回答1:

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.



回答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);



回答3:

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.



回答4:

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