views:

252

answers:

7

Lately I've been writing some JS code using jQuery and JavaScript as it is and I thought I will give JSLint a try. Let me say that the code contains various functions and jQuery usages and it works fine (without any errors ) in IE8 and latest Firefox. The code also validatas as XHTML 1.0 Transitional (and Strict too but I mostly want it to be Transitional valid).

However, with JSLint it's like everything is wrong. While I have read about it being very strict, even if I turn on only "The Good Parts" it's still like 70+ errors in a typical HTML page.

It starts out with this (why in the world would I want to remove the type to make my documents XHTML invalid??)

Problem at line 5 character 67: type is unnecessary.

<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>

and goes on with esoteric errors like

Problem at line 41 character 41: Use the array literal notation [].

var rows = new Array();

Problem at line 42 character 30: Too many var statements.

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

Problem at line 42 character 55: Unexpected use of '++'.

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

Problem at line 64 character 50: ['PrettyId'] is better written in dot notation.

var item = $("#item_" + data["PrettyId"]);

If anyone can provide me answers to these errors and especially, how to make JSLint be aware of jQuery and understand it, I will appreciate it.

If not, please explain whether you use it or not and whether you advice to use it or not.

UPDATE:

I'm going to wait one more day for more answers, if any, then I'll accept the answer with the most upvotes.

A: 

you should use it. The fact that it works in one browser doesn't mean it will work in all browsers; some are more lenient than others. for example, having a trailing comma in an array will break in IE but work in FF.

Be aware that sometimes you get a ton of errors, but you remove the first and a dozen go away, like compiling code.

you can do

var rows = [];

for the first error.

hvgotcodes
yeah but the first is "type is unnecessary"..how do I remove that?
mare
@mare, you take the type='text/javascript' out. JSLint is not perfect, but it will help you catch things. After a while you learn what to look for.
hvgotcodes
Your phrase "The fact that it works in one browser doesn't mean it will work in all browsers" worries me a little. It seems to imply that JSLint is a validator, and code that contains no JSLint errors will work in every browser. However, this is not necessarily the case. JSLint is *not* a validator. It simply points out *possible* problem areas in your code - parts that could be easily misunderstood, don't take into account function-based scope, or parts that *could* bring up difficult-to-debug errors.
Ryan Kinal
and even with regards to those difficult-to-debug errors I think it's just a way to scare people off, like "If you don't do it JSLint way (read, my way) you will eventually get into troubles"...quite an egotrip for this Crockfor guy..;)
mare
To be fair, Crockford knows his shtuff. And, having read *JavaScript: The Good Parts*, I understand where he's coming from with most of this stuff. Type coercion, truthy/falsy values, the nature of `undefined`, `null`, and `NaN`, as well `parseInt` can bring up some odd problems. Following JSLint guidelines can help you avoid those situations.
Ryan Kinal
You're probably right and he is too but as it is now, I think it decreases developer productivity since it only talks about "errors", when it would actually be better if those were "warnings". And when the "Good parts" is still way way too strict. I wonder how many manhours were vasted due to people trying to "decipher" his "errors" and his "view" on JS, I know for myself I already vasted 3 or more hours to only find out that his suggestions are so-so (it is nice if you follow them but even if you don't you most likely won't get into too big of a problem).
mare
I think this comes from a misunderstanding of what he's trying to accomplish with JSLint. As I've said, it is *not* a validator. It offers some good suggestions, but they are only that - suggestions. They may lack context, and they may not work for your particular application, but in general, they seem to be good practices. It's a tool to increase general code quality, not to identify errors in code.
Ryan Kinal
+1  A: 

There's an old joke about a programmer who smoked. A friend said, "You're a really smart guy, can't you read the warning on the pack that says cigarettes will kill you?" Came the reply: "I'm a programmer. We only pay attention to errors, not warnings."

Sometimes JSLint tells you things that are critical, sometimes it just nags. You can get lost trying to make it happy, but you might just be lost without it. Like any other tool, its input should be taken with a grain of salt. I prefer to think of it like the spell-checker or grammar-checker in MS Word. Sometimes it's right, sometimes it's wrong, and sometimes I just don't care what it tells me.

Robusto
JSLint is a a great tool, but as Robusto says, the output should be taken with a grain of salt. This is because it's not really a *validator*, it's a tool that enforces the "good parts" of JavaScript (as defined by Douglas Crockford). It has little to no concept of context, so some things it considers "wrong" may in fact be right for your particular situation.
Ryan Kinal
+1  A: 

Here are the best answers I can give. Perhaps someone can fill in some blanks. It doesn't appear as though any of these relate to jQuery, though.

Also, see this document for some explanations.

Problem at line 5 character 67: type is unnecessary.

<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
and goes on with esoteric errors like

I believe that for modern browsers, there's no need for text/javascript when linking to external js files.


Problem at line 41 character 41: Use the array literal notation [].

var rows = new Array();

It is recommended to not call the constructor when creating an Object or Array. I'm honestly not sure why. Anyone?


Problem at line 42 character 30: Too many var statements.

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

I suppose you have the i variable declared elsewhere in the same scope. A javascript block does not create scope, so if you have another for loop (for example) that uses i, it is using the same variable. No need to declare it again.


Problem at line 42 character 55: Unexpected use of '++'.

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

Not sure about this one, except that if I recall correctly, Crockford doesn't like the ++ and --.


Problem at line 64 character 50: ['PrettyId'] is better written in dot notation.

var item = $("#item_" + data["PrettyId"]);

I believe . notation is preferred because it is shorter and faster (in some browsers anyway). So data.PrettyID instead.

As far as I can tell, nothing here appears to be explicitly wrong. Mostly just best practice advice from JSLint creator's perspective.

patrick dw
About the "type" error...most modern browsers do handle it without type but W3C validator explicitly says that if type is missing the code is invalid. I want my HTML to be xHTML valid and I trust a group of W3C authorities more than Mr.Crockford..
mare
@mare - Valid point. I don't disagree. In fact, I'd ignore a number of these errors. I like `++`, I don't mind using superfluous `var` for clarity/safety, and, like you, I always include `type/javascript`.
patrick dw
In HTML5, the `type` attribute is now optional, and `type/javascript` is the default if its missing: http://www.w3.org/TR/html5/scripting-1.html#script
Yi Jiang
+10  A: 

A thing to remember when using JSLint is that is built on the opinion about what one person thinks is the "Good Parts".

I think is a great tool but there are rules that I don't agree with.

About the type attribute, you can find more about the opinion of the author here he says that the attribute is "required and non necessary", but if you validate your documents you clearly need it.

With the use of the Array literal notation [] vs. the Array constructor, I agree, there are differences that can make the two syntaxes behave different, for example:

 [5]; // one-element array
 ["5"]; // one-element array

 new Array(5); // empty array but its length is initialized with 5
 new Array("5"); // one-element array

So, for consistency an brevity the literal notation is better.

About the "Too many var statements", JavaScript has no block-scope, the scope is at function or global level, and all var statements are evaluated before the code execution -aka hoisting- and they are initialized with undefined, while the assignments are made at runtime.

For example:

var x = 0;
if (true) {
  var x = 1; // useless var, x already declared
}
x; // 1

And the "hoisting" of variable declaration can be shown in this example:

var x = 5;  // global
(function () {
  alert(x); // alerts `undefined`, x declared but unassigned in this scope
  alert(y); // ReferenceError, y is undeclared

  var x = 10;
})();

As you can see x holds undefined because it is declared before the actual code execution, the var statements are hoisted to the top of their enclosing scope:

var x = 5;  // global
(function () {
  var x;
  alert(x); // alerts `undefined`, x declared but unassigned
  alert(y); // ReferenceError, y is undeclared

  x = 10; // assignment is made
})();

So that rule wants to actually make the code to resemble what will happen, all the var statements at first place.

About the "Unexpected use of '++'", this is another rule that I don't quite like, the author thinks that "those contribute to bad code by encouraging excessive trickiness".

When I use them in some expression, I try to extract the operator usage to an alone statement, for example:

array[++id] = x;

To:

id+=1;
array[id] = x;

Which is more clearer, but anyway in the case of a for statement IMO it can't cause any confusion at all...

About the last one "['PrettyId'] is better written in dot notation.", JSLint expects the usage of the bracket notation to be "dynamic", it expects to see an expression there, not a String literal that contains a valid identifier name, the bracket notation should be used only when you want to access a property with a name that clashes with a reserved word e.g.:

data.function;    // SyntaxError in ECMAScript 3 based implementations
data["function"]; // Ok

Or when a property contains characters that are not a valid identifier, e.g.:

data.foo-bar;    // it access the property `foo` minus a `bar` variable
data["foo-bar"]; // Ok

data.foo bar;    // SyntaxError, unexpected `bar` identifier
data["foo bar"]; // Ok
CMS
+1 - Nice explanations. With regard to dot notation, you'd think JSLint would compare the string against the current/future reserved words. Just one note, in your second example that uses `alert(x)`, I think you forgot to update the subsequent code comment. It currently reads `// alerts undefined, x declared but unassigned`. Didn't want to change it in case I was misunderstanding your point. :o)
patrick dw
@patrick, Thanks, it's a copy paste error, the `var` statement and the assignment should be splitted up to show the behavior, so the comment stays ;)
CMS
Please add this in your answer of how to make JSLint aware of jQuery's dollar sign: /*global DOMAssistant, $, $$ */
mare
Also besides your "var" error explanation, this error is also triggered when you have var usages like this: var a = 0; var b = 0; the error goes away if you do var a = 0, b = 0; Please add this too to your answer.
mare
I tried to reproduce the example you give straight after "And the "hoisting" of variable declaration can be shown in this example:" line, and the alert(x) brings up "5" in the message window, not 'undefined', which seems to be correct since x in in the closure. Could you clarify?
Art
@Art: That's strange, the `x` variable is instantiated in the local variable environment *before* the anonymous function is executed -even if the `var` statement is at the bottom that function-, and it is initialized with `undefined`... try the example [here](http://jsbin.com/elotu4/edit)...
CMS
@CMS Strange indeed, when I do this http://jsbin.com/elotu4/2/edit it works exactly as I described.
Art
@Art, I saw your example, it alerts `1` because there `x` variable is not declared in the local scope -the scope of the function-, the *hoisting* behavior in your example will appear when a variable named `x` is declared anywhere in that function -it will *shadow* the outer `x` variable-, even after your alert, check [this](http://jsbin.com/elotu4/3/edit) modified version of your example.
CMS
@CMS, Thanks, I see that thw problem is now. So the actual declaration of x within the scope, even at the bottom, makes all the difference!
Art
@Art, yep, you got it... you could thing that the alert should show `1`, because the `var` statement is *after* that, but that doesn't happen, *hoisting* ;)
CMS
+3  A: 

I use jslint on .js files and find a combination of options and fixes to make it happy. I find it improves my code quality. I would recommend running it, even if you only use it to isolate omitted 'var' declarations.

I avoid the script tag warning by not running against html files. I use jslint systematically on .js files, but not on html. I find it is just too burdensome to declare all the global identifiers that got defined in included scripts, but aren't visible to jslint.

Crockford's book 'Javascript: The Good Parts' explains many if not all of the jslint warnings, and some of them are based on perceived bug proneness. The 'new Array()' vs ' []' warning is based on Doug's aversion to the 'new' operator. Omitting 'new' for various constructors is commonly valid code, but not correct code, and using the alternative syntax avoids that risk.

The 'too many vars' error means just that, a large number of 'var' declarations in a given function: the Crockford endorsed style is to use one or very few 'var' declarations, all at the top of the function. You can declare multiple variables in one var statement, by separating them with commas.

The '++' caution is another bug proneness based warning; Using '+=1' means the same thing, and Doug believes it to be less error prone.

jslint is thus a mixed bag. Some features (locals vs globals) are invaluable, some (script types) are just annoying, and many are of dubious benefit but harmless.

jQuery itself passes jslint checks, as described here: http://docs.jquery.com/JQuery_Core_Style_Guidelines#JSLint

pduel
nice answer....
mare
A: 

JSLint is a Code Quality tool. It's not like W3C validator. Consider it something like a weekly code review at a company. Coding conventions vary and JSLint is just one of them. There may be points you don't agree with, but if you work in a team and you need to manage a larger codebase JSLint can be a life saver. Why? Because it warns you about things that are confusing or error prone.

The best way to use JSLint is this: read everything it says and if you're unsure about something correct it as suggested (as it seems to be the case here).

The reason is that JSLint is meant to avoid confusion and if you're using something that can lead to errors and you don't know why, then you better off with a clear alternative.

And if you want to know the reasoning behind the suggestions watch Douglas Crockford's videos on Javascript.

Finally, you can turn off filters that you find useless.

galambalazs
A: 

It hurts when you start using it on your old code.

But then it will save you a lot of time.
JSLint can detect many problems that you would only see when refreshing your page or worse when your users do.
Now it hurts me when I have to use an editor without JSLint

Another advantage is when you start compressing your javascript. If you pass the JSLint checks, you are almost certain to compress without problems.

That being said, jquery has 23 warning, most of them about regex, but is widely used without any problems.

Mic