What is the reason behind JSLint saying there are "too many var statements"

JavascriptRefactoringJslint

Javascript Problem Overview


JSLint (with the onevar flag turned on) is flagging some javascript code that I have with the following:

Problem at line 5 character 15: Too many var statements.

I am happy to fix these errors, but I'd like to know, am I doing it for performance or because it is just a bad practice and has a greater potential to introduce bugs in my javascript code. What is the reason behind the onevar flag?

I did look at the JSLint docs for the var keyword but it doesn't specifically talk about why multiple var statements in the same function are bad.

Here is an attempt at an example. Explain how the code will benefit from only having 1 var statement:

function Test(arg) {
   var x = arg + 1,
       y = cache.GetItem('xyz');
   if (y !== null) {
      // This is what would cause the warning in JSLint
      var request = ajaxPost(/* Parameters here */);
      
   }
}

Javascript Solutions


Solution 1 - Javascript

Javascript does not have block scope. In other languages with it (like c), if you declare a variable in the if statement, you can not access it outside of it, but in javascript you can. The author of JSLint believes it is a bad practice, since you (or other readers) might get confused and think that you can no longer access the variable, but you actually can. Therefore, you should declare all your variables at the top of the function.

Solution 2 - Javascript

The official reason is here, by Douglas Crockford.

To quote:

> In many languages, a block introduces a scope. Variables introduced in > a block are not visible outside of the block. > > In JavaScript, blocks do not introduce a scope. There is only > function-scope. A variable introduced anywhere in a function is > visible everywhere in the function. JavaScript's blocks confuse > experienced programmers and lead to errors because the familiar syntax > makes a false promise. > > JSLint expects blocks with function, if, switch, while, for, do, and > try statements and nowhere else. > > In languages with block scope, it is usually recommended that > variables be declared at the site of first use. But because JavaScript > does not have block scope, it is wiser to declare all of a function's > variables at the top of the function. It is recommended that a single > var statement be used per function. This can be declined with the vars > option.

Solution 3 - Javascript

Just declare your vars in one place like this:

var request,x,y;

Solution 4 - Javascript

If the "onevar" option is set to true if only one var statement per function is allowed.

if (funct['(onevar)'] && option.onevar) {
    warning("Too many var statements.");
}

Solution 5 - Javascript

The reasoning is already described.

Recommendation is to use this form:

var myVar1 = document.getElementById("myDiv1"),
  myVar2 = document.getElementById("myDiv2");

or this:

var myVar1, myVar2;
myVar1 = document.getElementById("myDiv1");
myVar2 = document.getElementById("myDiv2");

But this doesn't look very nice, especially if you want to document vars.

So you can just disable this warning temporarly:

  /*jslint vars: true*/
  /**
   * @returns {HTMLDivElement}
   */
  var myVar1 = document.getElementById("myDiv1");
  /**
   * @returns {HTMLDivElement}
   */
  var myVar2 = document.getElementById("myDiv2");
  /*jslint vars: false*/

Warning: make sure that this is done at the top of a function.

I think this is done because jslint couldn't reliably determine if vars were declared at the top of function or not.

Solution 6 - Javascript

Just a guess here, but it may be time for functional decomposition. Functions should do one thing and do it well.

Too many vars is suggestive of a function that's trying to do too much. Or a case where you should be using an array.

Solution 7 - Javascript

The idea is that you should use an object instead of individual vars. So where you have got:

var x = arg + 1,
    y = cache.GetItem('xyz');

Change it to:

var dimensions = {};
dimensions.x = arg + 1;
dimensons.y = cache.GetItem('xyz');
dimensions.request = ...

You can then access these variables through the object, its neater to have one object per function to contain that functions variables. Then you won't get the warning.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionslolifeView Question on Stackoverflow
Solution 1 - JavascriptswampsjohnView Answer on Stackoverflow
Solution 2 - JavascriptElzo ValugiView Answer on Stackoverflow
Solution 3 - JavascriptRoy WalterView Answer on Stackoverflow
Solution 4 - JavascripttomView Answer on Stackoverflow
Solution 5 - JavascriptVanuanView Answer on Stackoverflow
Solution 6 - JavascripttpdiView Answer on Stackoverflow
Solution 7 - JavascriptSteven RobinsonView Answer on Stackoverflow