5

I am well aware of similar questions, but I still can't solve mine basing on those.

So, my code looks like this:

for (var e, i = 0; e = formErrors[i]; i += 1)

JSHint returns said error in char 39, so with ; after formErrors[i]. What can I do?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Tomek Buszewski
  • 7,659
  • 14
  • 67
  • 112

4 Answers4

10

JSHint is warning you of a potential bug. It is expected that the 2nd part of a for statement will be a Boolean expression. Normally, you'd use one of the comparison operators for this (==, ===, !=, > etc..). Since the expression is e = formErrors[i] it looks like it might be a mistake, possibly due to a missing equal sign. This is a common typo that causes a lot of bugs.

Apparently, in this case it is not a bug, but rather an intentional usage of the fact that any expression evaluates to something, and an assignment expression evaluates to the assigned value:

var x;

alert(x = 1);

So the for statement actually assigns a new value to e, but also evaluates that value as a condition, casting it to Boolean if required.

You could refactor your code such that it both assigns the value and uses a casting operation that would satisfy JSHint and make the code a bit more obvious to the reader:

for (var e, i = 0; !!(e = formErrors[i]); i += 1)

The 2nd ! (the one directly in front of (e...) causes a casting to Boolean, but also negates it, the 1st ! reverts this negation.

Community
  • 1
  • 1
Amit
  • 45,440
  • 9
  • 78
  • 110
  • Better use `!!(e = formeErrors[i])` instead of that ugly `false == !…`. Then have an upvote – Bergi Oct 22 '15 at 08:36
  • @Bergi thought about it, found it ugly as well... thought of `true == !!(..)`, still ugly... – Amit Oct 22 '15 at 08:38
  • Nah, that's not ugly, but rather [a common js idiom](http://stackoverflow.com/q/784929/1048572). If you don't like it, `Boolean(e = formErrors[i])` would be an alternative, but please stop comparing booleans to booleans. – Bergi Oct 22 '15 at 08:40
  • @Bergi - are you sure that's enough to satisfy JSHint? – Amit Oct 22 '15 at 08:43
  • I had not tried but did expect it to. Edit: And [when I did](http://jshint.com/), your version actually warned "*Use `===` to compare with `false`*" and about "*confusing use of `!`*" (just what I was saying :-)), while both `!!` and `Boolean` worked. – Bergi Oct 22 '15 at 08:46
  • Thanks for the code and for the explanation! Nevertheless, we did a rewrite to make the code clearer to somebody that'll read it couple of months from now ;-) – Tomek Buszewski Oct 26 '15 at 13:10
  • For standardjs (which I think is built on jslint), with the --fix argument, it stripped out the `!!(...)` idiom, then complained again! I tried `Boolean()`, and it stripped out the `Boolean` part, but has left the outer parentheses. I.e. I think `(e = formErrors[i])` might be the recommended solution now? – Darren Cook Oct 20 '17 at 08:02
  • @DarrenCook I think you're right. ESLint returns an error on `!!(e = formErrors[i])` with description `Redundant double negation/ (no-extra-boolean-cast)`. It should work without the `!!` in front of the brackets: https://eslint.org/docs/rules/no-extra-boolean-cast – jnaklaas Jan 29 '19 at 09:50
2

That's just a very weird way of writing a loop. JsHint expects a boolean expression ("conditional") there, and judges that your assignment is a mistake and you actually wanted a comparison (== instead of =).

What you should do is switch to the following common array iteration idiom:

for (var i = 0; i < formErrors.length; i += 1) {
    var e = formErrors[i];
    …

(Which works the same as your original code for non-sparse formErrors arrays that contain no falsy values.)

Or alternatively, if you want to write non-idiomatic code, dump jshint :-)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

e = formErrors[i] is an assignment, don't you want a condition there? use a comma after i=0 in that case, else put a condition after the semicolon.

Saransh Kataria
  • 1,447
  • 12
  • 19
0

Typically, the middle element in a for loop is the condition that is used to decide whether to continue the loop or not. You have an assignment there, if you wanted a condition you should use e === formErrors[i] (or with a double =, but that is usually not recommended).

An assignment can technically work, because e can be, for example, some object (true) or null (false). But that is considered bad coding style, usually, and won't make for very readable code.

ralh
  • 2,514
  • 1
  • 13
  • 19