79

JSLint site updated, and I cannot check JS scripts anymore. For me, this warning is not critical, and I don't want to go through thousands of lines to fix this, I want to find more critical problems.

Does anybody know how to turn off this error, or use legacy JSLint?

UPDATE

Example:

function doSomethingWithNodes(nodes){
  this.doSomething();

  for (var i = 0; i < nodes.length; ++i){
    this.doSomethingElse(nodes[i]);
  }

  doSomething(); // want to find this problem
}

jslint.com output:

Error:
Problem at line 4 character 8: Move all 'var' declarations to the top of the function.

for (var i = 0; i < nodes.length; ++i){

Problem at line 4 character 8: Stopping, unable to continue. (44% scanned).

Problem:

Having variables on top of the functions is new requirement. I cannot use JSLINT to test code, because it stops scanning script on this error.

I have a lot of code, and do not want to threat this warning as critical error.

UPDATE 8/22/2011: found http://jshint.com, it looks much better than http://jslint.com/

Oleg Yaroshevych
  • 1,285
  • 1
  • 11
  • 9

7 Answers7

151

Update June, 2017: Subject to support (e.g. if you're not running JavaScript in Internet Explorer 10 or below), you should look into using let instead of var.

For example: for(let i=0; ...; i++)


There's no way I'm going to put var i; from a for(var i=0; ...; i++) at the top of my functions. Especially when The JavaScript Specification has it as an acceptable syntax in the for section (12.6). Also, it's the syntax Brendan Eich uses in his examples.

The idea of moving the declaration to the top is that it is supposed to more accurately reflect what happens under the hood, however, doing so will only reflect, not affect.

For me, this is a ridiculous expectation for for iterations. More so because JSLint stops processing when it detects it.

Whether having variables declared at the top of a function is more readable is debatable. I personally prefer iterator variables to be declared when they are used. I don't care if the variable is already created internally, I'm initialising it here so I am safe.

I would argue that declaring an iterator variable where they are used ensures they are not accidentally made global (if you move the loop out into another function, the iterator variable moves with it). This is much more maintainable than having to maintain variable declarations at the top of functions.

For now, I'm using http://www.javascriptlint.com/online_lint.php because it seems to focus on the important stuff.

Lee Kowalkowski
  • 11,591
  • 3
  • 40
  • 46
  • 12
    Also, check out JSHint, which was created partially in response to stuff in JSLint like this. And see this discussion: http://stackoverflow.com/questions/6803305/should-i-use-jslint-or-jshint-javascript-validation/10763615#10763615 – B Robster Jun 22 '12 at 15:25
  • If you're only interested in syntax issues and not so much style, then Google's closure compiler looks the part: http://closure-compiler.appspot.com/home - details at: https://developers.google.com/closure/ - They have a downloadable linter too, but I haven't used it. – Lee Kowalkowski Sep 13 '12 at 12:34
  • 1
    Thanks for pointing to http://www.javascriptlint.com/online_lint.php. I had been using JSLint, but it's hard to wade through all the pointless drivel about errors that aren't even errors on JSLint. –  Sep 21 '12 at 14:15
  • 14
    I don't disagree with you, but it is important to point out that javascript has only function scope. It does not have block scope in a for loop. Therefore even though the variable `i` is defined in `for(var i=0; i<10; i+=1)` it will be available to the entire function, and be hoisted to the top on initialization. JSLint is syntactically correct, but in this case, by convention nobody codes in that manner. – mastaBlasta Mar 18 '13 at 13:54
  • @mastaBlasta JSLint is not syntactically correct, it's purely a matter of style. There is nothing in the JavaScript specification that says a declaration (variable or function) must be declared before it is used, JavaScript does this for you. Mirroring the internals of a language is unnecessary and a potential anti-pattern in this instance of `for` loops, given the example of accidentally making variables global when moving loops to other functions. Many coding standards say you should declare variables as close as possible to where they are used. – Lee Kowalkowski Mar 19 '13 at 09:44
  • 2
    NVM you're totally right. I was testing to see what would happen if you had two loops in a function `for(var i=0; i<5; i+=1)`, if the compiler would throw a `variable already defined` warning, but it didn't! Even in strict mode, re-declaring a variable threw no warnings or errors. So then yes, JSLint is wrong. – mastaBlasta Mar 19 '13 at 17:48
  • 1
    If Crockford thinks it's confusing that a variable declared in a scope is actually available to the entire function, why not detect usages of this variable outside the scope and warn against that instead? Personally I would place `i` at the top if I have two `for` loops that use it. The purpose of placing variable declarations in a scope is to convey the information that they are supposed to be used in this scope only, you lose that information by moving them to the top. And the fact that they're created at the beginning of the function doesn't matter, JS has no `constructor` anyway. – Gary Chang Aug 07 '13 at 15:43
  • @mastaBlasta, I used to re-declare variables all the time, at each block they are used. I thought it was good style because you don't have to worry about variable declarations or the risk of leaking to the global scope at all when you move blocks of code around. But lots of static analysis tools warn against this, and I later abandoned this practice. However I still don't get why this is considered harmful. – Gary Chang Aug 07 '13 at 15:46
  • JSLint is a **joke**. It's great if you're Douglas Crockford, because it checks code against _his personal coding style_, so it can help _him_ catch issues **he** believes are issues. There's something very wrong if he thinks other people should use this and that all code should follow his strict guidelines, even though it has NO co-relation to practical coding or standard use. It doesn't even have any options to customize the errors, it's garbage. – bryc Jul 20 '15 at 13:53
  • It has hurt your feelings? That's what it's for - read the manual! It is not a matter of errors, but a matter of style, leading to safer coding. Also declaring var i outside the loop atop of function allows reusing it in other consequent for loops. No need in ii, iii, j, k, l and other inventions. – Zon Sep 09 '15 at 13:49
  • 2
    @Zon: or just use `i` again like any sane developer would. Doesn't matter where you declare `var i`, reuse is allowed regardless. – Lee Kowalkowski Sep 09 '15 at 13:52
7

Google Closure compiler will actually fail to correctly detect the type of the loop variable of a for...in loop unless it's declared like for (var i in ...) and no annotation seems to fix this, so the declaration cannot be moved to the top.

jjrv
  • 4,211
  • 2
  • 40
  • 54
  • Oh really?! That's a pity, but really useful to share, +1. – Lee Kowalkowski Nov 13 '12 at 21:13
  • @jjrv do you have an example of code that doesn't work with the closure compiler? I am using it and have not seen any issues. – JavaKungFu Jan 08 '13 at 22:32
  • @JavaKungFu the symptom was that the compiler reports less than 100% typed code and shows a warning if you set reportUnknownTypes = CheckLevel.WARNING in CompilerOptions.java. – jjrv Jan 09 '13 at 08:33
  • Oh OK, I misunderstood your answer, I thought it actually created a problem in the compiled code. Thanks. – JavaKungFu Jan 09 '13 at 15:04
5

You can download legacy versions anytime, or modify the latest version. It's not that hard, really (search for move_var). Then run jslint locally, either using node, or using a browser with a simple HTML form - you may want to copy Crockford's original.

Note that the warning was introduced as part of a major rewrite, and only occurs after for(, so the message is a little misleading.

user123444555621
  • 148,182
  • 27
  • 114
  • 126
4

Note that move all vars to the top is different from "allow one var statement per function". The requirement to move all variables to the top is new and doesn't seem to have a switch. More at http://groups.google.com/group/jsmentors/browse_thread/thread/5e90c25230f8e22/70e1a95a20fb829e

Paul Beusterien
  • 27,542
  • 6
  • 83
  • 139
3

I had this problem on my codebase, when we wanted to switch to the latest version of JSLINT. We had a lot of those and people were not happy about moving the declaration. We actually found the most elegant solution was to use underscore.js and instead of having the full verbose loop, to use the _.each() function, which removed the JSLint error and made our code more functional, cleaner, tighter and easier to read.

Simon Kenyon Shepard
  • 849
  • 2
  • 11
  • 23
1

Even though the new beta JSLint doesn't document a comment directive for multiple var tolerance within a function, it does appear to support the directives from the original version.

The original JSLint allowed you to do this:

/*jslint vars: true */

In my experience this still works—I suppose for backwards compatibility. The time of this writing is June 2015.

Peter
  • 3,998
  • 24
  • 33
0

I found that the following syntax will get the error removed:

function doSomethingWithNodes(nodes) {
    this.doSomething();
    var i; // HERE is where you move the 'var' to the top of the function
    for (i = 0; i < nodes.length; ++i) {
        this.doSomethingElse(nodes[i]);
    }

    doSomething(); // want to find this problem
}
Alexis Tyler
  • 1,394
  • 6
  • 30
  • 48
Gio
  • 1