TLDR: Why are function parameters not treated as var
declarations?
Using var
, redeclaring a variable declared using var
has no effect. The original declaration remains in effect.
However, using var
in this way will mask a parameter of the same name.
Why is the language designed like this?
In the following, variable var bar
is treated as a new declaration and not a redeclaration of parameter bar
.
function foo(bar = 0, bam = () => bar) {
var bar = 1
return bam()
}
console.log(foo()) // 0
Is it designed like this because arguments and local variables are semantically fundamentally different, and fall into two categories?
I might have expected parameters to be treated like var
declarations, but they aren't. They appear to be in their own "box" on the scope chain.
So the scope chain of a function looks like this:
function body >> parameter list >> outer function body >> outer parameter list >> ... global scope
Are arguments and local variables semantically fundamentally different, and fall into two categories?
No, not really. In fact, in many cases they are indistinguishable, creating variables in the same scope - just not here in the example you gave.
I might have expected parameters to be treated like
var
declarations, but they aren't. They appear to be in their own "box" on the scope chain.
Yes. That's because you are using default initialisers in your parameter declaration, which gives the parameters their own scope, and the function body scope is a child of that. Still, var
s are getting declared in that body scope (not getting hoisted).
It might be fitting to say that parameters are treated like let
declarations since ES6, except where they need to be treated as var
declarations to preserve backwards compatibility (allowing re-declarations). See here or there for details.
The concept of variable hoisting
and clouser
in javascript states that variables remembers enviornment in which they are created.
Now lets have a look in your example line by line
function foo(bar = 0, bam = () => bar) { // here bar 0, and function `bam` will remember bar value as 0 whenever it gets called
And when you are reassigning bar
to 1
in function foo
, function bam
will not update it. As both function have different scopes.
So as per the javascript concept, this is correct and desired behaviour.
Update:
function foo(bar = 0, bam = () => bar) {
bar = 1
return bam()
}
console.log(foo()) // 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With