Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does redeclaring an identifier in a function, mask a parameter of the same name?

Tags:

javascript

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
like image 471
Ben Aston Avatar asked May 04 '20 08:05

Ben Aston


2 Answers

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

like image 189
Bergi Avatar answered Nov 06 '22 23:11

Bergi


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
like image 1
Kenny Avatar answered Nov 06 '22 22:11

Kenny