We know that every function creates its own context and can have its own local variables and things.
We therefore presume that writing var a = [5]
, in the context of top most function context, will make it available and accessible by the context of any new nested functions we may write.
And this is where we encounter a behavior which is most probably 'undocumented' as well as 'unexpected'.
The 1at example of the op
function bar(){
if(!a) {
var a = [1,2];
}
console.log(a);
}
>> 1,2
has it return a local value of 1,2.
where we can see that the if conditional of the bar function context is treating the host function variable a, as undefined wherefore it is negating it !a to true.
Why is that?
A commentator insists in hoisting. But what hoisting?
There's absolutely no interference of a hoisting principle in a final result or behavior in the two versions of the same function at which the only difference is in conditional argument: one checks if 'a' is false and the other, if it's true.
Hoisting! What hoisting?
If it were for "hoisting" - the !a operation should unmistakably return false because of the fact that a is already defined with a truthy value on a higher context accessible to any and every lower context functions of the host. But quite the contrary
As a consequence of if(!a [false] ) therefore true from conditional return, it is allowing the execution of a new declaration of a variable with the same name using the var key, as if it's out of reach or doesn't exist in a higher scope at all.
And it shouldn't. But it should.
Now trying the same thing without the negation of the if argument in conditional, we'll get an error and an assignment failure as in:
function bar(){
if(a) {
var a = [1,2];
}
console.log(a);
}
>> undefined
[!same as when using if(!!a) ]
We've changed nothing except that now we are asking if a is true so that we can create a new local 'a' variable with value [1,2];
What is going on?!
The if conditional which is in explicit need for the a argument to be true in order to proceed is looking up and "climbing it down" to the local context of the function bar.
For some reason it is handled as an attempt to re-declare the variable of a host function and refusing to initialize and assign a value to new variable with the same name in a local context. That's a confusion because of the conditional which now refers to the host variable it is refusing to declare and assign a value to a local a.
However, on the console log a local variable a is being returned and it is undefined.
Which is unexpected; contradictory; defiant but seemingly correct!
It is correct because the local a variable was initialized but didn't get a value correctly to begin with. We've tried to re-declare the one from the higher context, and it wasn't allowed.
The only good thing is - the behavior appears to be uniform across browsers.