61

Is defining JavaScript variables inside if-statements correct?

if(a==1){
    var b = 1;
} else {
    var b = 0;
}

I know the code above will work, however, WebMatrix highlights the variables.

Should I define the variables outside the if-statement? Or the first option's correct? Or it doesn't really matter?

var b = '';
if(a==1){
    b = 1;
} else {
    b = 0;
}
lukeshek
  • 978
  • 2
  • 9
  • 17

5 Answers5

76

As of the official release of ES2017 spec (2017-07-08), EcmaScript does support true block scope now using the let or const keywords.


Since ECMAscript doesn't have block scope but function scope, its a very good idea to declare any variable on the top of your function contexts.

Even though you can make variable and function declarations at any point within a function context, it's very confusing and brings some weird headaches if you aren't fully aware of the consequences.

Headache example:

var foo = 10;

function myfunc() {
    if (foo > 0) {
        var foo = 0;
        alert('foo was greater than 0');
    } else {
        alert('wut?');
    }
}

Guess what, we're getting a 'wut?' alert when calling myfunc here. That is because an ECMAscript interpreter will hoist any var statement and function declaration to the top of the context automatically. Basically, foo gets initialized to undefined before the first if statement.

Further reading: JavaScript Scoping and Hoisting

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • 1
    +1 for link [JavaScript Scoping and Hoisting](http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html) — it clears any confusions one might have on the topic –  Nov 23 '17 at 09:54
  • 3
    So what is the solution here if you don't want to redefine variables globally and do want to change a variable based on which path it takes through an if statement? Is creating an object and redefining the object property the only solution? – forestkelley Apr 07 '19 at 00:59
4

Note that ECMAscript 6 does support block-level variables using the 'let' rather than the 'var' keyword. While variables declared with 'var' are hoisted to be function-scope regardless of where they are declared, those defined using 'let' are scoped to the enclosing block only.

farhadf
  • 1,918
  • 3
  • 19
  • 27
2

Putting a var inside an if statement is not against "the rules" of the language, but it means that, because of var hoisting, that var will be defined regardless of whether the if statement's condition is satisfied.

  • what if i have something like if (a> b) { var text = $('.p-text').detach(); $('.p-options > *:nth-child(3)').after(text); } else { var text = $('.p-text').detach().appendTo('.p-info'); text.find('div[data-p-wrapper]').detach().prependTo(text); } – Adeerlike Jul 04 '18 at 12:26
1

See function four on What is the scope of variables in JavaScript?

As of 2012, there's no block-level scope in JavaScript. So your first version is fine: the variables are defined in the scope outside the if block.

hcarver
  • 7,126
  • 4
  • 41
  • 67
  • 1
    There is block level scope in JavaScript. The [let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) keyword. – WebWanderer Apr 16 '15 at 20:48
  • 1
    Not yet there isn't! Let is currently a Release Candidate for ECMAScript version 6 (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Specifications). So give it another 3 years and it might be widely implemented enough to be useful in the wild. – hcarver Apr 16 '15 at 21:10
  • Just for the sake of completeness, there are compilers, e.g., [Babel](https://babeljs.io/) (and maybe a few others) that can convert your next-generation JavaScript into plain old JavaScript, so you don't really have to wait another 3 years. – Septagram Jun 12 '16 at 15:00
1

Because JavaScript's variables have function-level scope, your first example is effectively redeclaring your variable, which may explain why it is getting highlighted.

On old versions of Firefox, its strict JavaScript mode used to warn about this redeclaration, however one of its developers complained that it cramped his style so the warning was turned off. (Current versions of Firefox support a block-level variable declaration syntax.)

Neil
  • 54,642
  • 8
  • 60
  • 72