14

For the following code, as I have redeclared a with var a, my expectation for alert(a) is to show undefined, but why it shows 4?

function f(a) {
  var a;
  alert(a);
}

f(4);
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
  • 1
    jslint or other linters will report an error such as "Redefinition of `a`:, –  Jan 11 '16 at 04:21
  • Also, if you use `let` instead of `var`, the interpreter (or transpiler) itself will produce a useful error. –  Jan 11 '16 at 04:27
  • Your title is quite misleading, you arent redefining variable here – A. Wolff Jan 16 '16 at 00:45

2 Answers2

8

In JavaScript, a variable is either global or local to a function. There is no such thing as nested scopes within a function (unless you actually nest one function inside another function).

Quoting Mozilla's JavaScript docs:

The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global.

Since both the function parameter a and your var a are declared in the same function scope, they resolve to the same variable.

See also: What is the scope of variables in JavaScript?


Note that object fields can also sort of be considered another level of scoping—but that isn't really relevant to your question.

Also—as torazaburo points out in his comment below—ECMAScript 6 introduced a let keyword, which lets you create true nested scopes within functions. However, this feature is new enough that I didn't originally consider it worth mentioning (since it's not really safe to use in production code just yet). E.g., it looks like Firefox won't officially support the new let construct until their new release at the end of this month (January 2016).

Community
  • 1
  • 1
DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • 1
    *There is no such thing as nested scopes within a function* But what about `let`? –  Jan 11 '16 at 04:54
  • 1
    @torazaburo - Good point. However, since `let` was just standardized last year, it'll probably be a while before it's actually safe to use in the wild without [jumping through hoops](http://stackoverflow.com/questions/30529367). – DaoWen Jan 11 '16 at 05:05
5

Declarations are moved to the top of their scope in a process called hoisting.

For example:

var a = 5;
var a = 6;
var a;

becomes something like

var a = undefined;
a = 5;
a = 6;
a;

Therefore, attempting to redeclare an already declared variable without using any assignment does nothing.

In your case, the variable a is already declared as a parameter of the function. So var a; is useless. If you want to set it to undefined, use a = void 0;.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • I don't get it--what is the relevance of hoisting here? –  Jan 11 '16 at 04:27
  • @torazaburo Whn a variable is declared with `var a;`, its value will be undefined. But declarations are moved to the top because of hoisting, so a variable can't be redeclared. At least that's how I understand it. – Oriol Jan 11 '16 at 15:06