147

What is the best practice for that then?

Jslint explains that it "adds confusion". I don't see it really...

EDIT: The code, as requested:

  var all,l,elements,e;
  all = inElement.getElementsByTagName('*');
  l = all.length;
  elements = [];
  for (e = 0; e < l; (e++))
  {
    if (findIn)
    {
        if (all[e].className.indexOf(className) > 0)
        {
            elements[elements.length] = all[e];
        }
    } else {
        if (all[e].className === className)
        {
            elements[elements.length] = all[e];
        }
    }
  }
KdgDev
  • 14,299
  • 46
  • 120
  • 156
  • 1
    Could you please give us the entire line? Normally wrapping parens around the operator and its operand will solve this, – Sean Kinsey Jun 08 '10 at 18:48
  • @WebDevHobo That code doesn't show that error in JSLint for me. Sure it's the right snippet? – Samir Talwar Jun 09 '10 at 18:25
  • @Samir: down by the options, click "the good parts" and have it checked again. – KdgDev Jun 11 '10 at 13:17
  • 2
    @WebDevHobo That checks "Disallow `++` and `--`". Of course it's going to complain about it. ;-) – Samir Talwar Jun 11 '10 at 13:58
  • 173
    This must be the *dumbest* check in JSLint. Seriously? When has `++` or `--` ever caused a programmer any confusion? I love JSLint, but *COME ON.* – Stephen Nov 02 '10 at 15:12
  • Just found out that `(i -= 1)` does not seem to work, so I had to use `(i += -1)` – rmartinus Nov 09 '11 at 00:40
  • 2
    @blackrocky Is that supposed to be less confusing than i--? :) – Igor Jerosimić Dec 11 '11 at 21:32
  • 2
    In my opinion, the enforcement of `} else {` is the dumbest thing in JSLint. – Almo Jun 14 '12 at 15:21
  • @Stephen Try [JSHint](http://www.jshint.com). JSLint didn't work for me due to being exceedingly strict about every little thing with no option to turn things off. – Roman Starkov Aug 09 '12 at 20:33
  • 1
    I was on the side of crockford in his rantings, but this, this is nuts. What is wrong with i++, that is one of the first things everyone learns. – NimChimpsky Sep 13 '12 at 14:37
  • 2
    @Stephen and Almo you're both wrong. The daftest check is not allowing for (var i = 0; ... FYI I use and love jsLint for Notepad++ which lets you easily 'tolerate' these things, and lets you use jsHint as well. – David Gilbertson Apr 22 '13 at 02:22
  • 14
    `Line 26 // WARNING: JSLint will hurt your feelings.` – yuan Jul 01 '13 at 11:43

8 Answers8

94

The longstanding best practice: use i += 1 instead, following jslint's advice.

As for why it is a better practice than ++, according to Crockford:

The increment ++ and decrement -- operators make it possible to write in an extremely terse style. In languages such as C, they made it possible to write one-liners that: for (p = src, q = dest; !*p; p++, q++) *q = *p; Most of the buffer overrun bugs that created terrible security vulnerabilities were due to code like this. In my own practice, I observed that when I used ++ and --, my code tended to be too tight, too tricky, too cryptic. So, as a matter of discipline, I don’t use them any more.

Edit: Included comment from Nope as this answer continues to get views.

halfer
  • 19,824
  • 17
  • 99
  • 186
unomi
  • 2,642
  • 18
  • 19
  • 10
    This doesn't really explain the 'adds' confusion' bit. @samir-talwar adds an explaination. – Matt Clarkson Sep 12 '11 at 13:44
  • 29
    @MattClarkson: According to Crockford: *The increment `++` and decrement `--` operators make it possible to write in an extremely terse style. In languages such as C, they made it possible to write one-liners that: `for (p = src, q = dest; !*p; p++, q++) *q = *p;` Most of the buffer overrun bugs that created terrible security vulnerabilities were due to code like this. In my own practice, I observed that when I used `++` and `--`, my code tended to be too tight, too tricky, too cryptic. So, as a matter of discipline, I don’t use them any more.* – Nope Mar 28 '13 at 09:56
  • 5
    @MattClarkson: In `for` its use is clear and no confusion occurs but the use can be cryptic and confising in other circumstances. I assume to prevent writing cryptic code in other, more complex code segments it is best avoided all together. It is only a recommendation and can be ignored :) – Nope Mar 28 '13 at 10:00
  • 4
    @FrançoisWahl Thanks for the *Crockford* explaination – Matt Clarkson Mar 28 '13 at 12:03
  • 5
    Just ignore it; JSLint sometimes has very weird interpretations on things... Handy in times but annoying on other times. – Lawrence Jan 14 '14 at 13:45
  • Prefix/Postfix operators have a higher precedence than += and -= operators and this is the main reason why I use operators in while-loops as they are evaluated before <,<=,>=, > and other equality operators... At least that is what I thought until I ran a few tests on chrome and firefox and for reasons I can't explain changing this statement: while (num-- > 0 ) { code } to: while (num-=1 > 0) { code } worked the same. This made no sense according to this operator precedence table: http://www.scriptingmaster.com/javascript/operator-precedence.asp – Eggs May 18 '17 at 05:53
  • @Eggs num-- will return the value before being modified var num = 0; console.log(num++, num); 0 1 I don't think this has much to do with precedence, more with how the operator itself returns. btw: I am not seeing that they are the same: var num = 2; while(--num > 0){console.log(num)} 1 eod var num = 2; while(num-- > 0){console.log(num)} 1 0 eod var num = 2; while(num -= 1 > 0){console.log(num)} 1 eod – unomi May 19 '17 at 12:25
  • JSLint actually suggests that to avoid the kinds of confusion discussed in answers on the thread, you can use [i++] which is accetable. It also works on array[key++] = foo; so you can use it, if it's readable and not going to get confused, like the a++ + ++b examples. [a++] + [++b] is hardly great (or likely) but I consider it unlikely that someone will insert a space which creates an accidental bug... (less likely) – wcndave Dec 12 '18 at 15:35
88

Just add /*jslint plusplus: true */ in front of your javascript file.

Rico Sonntag
  • 1,505
  • 1
  • 15
  • 21
  • 7
    Though as of July 9th, 2014, Crockford warns that [he's removing that option](https://plus.google.com/+DouglasCrockfordEsq/posts/aBLU9y4Fd4z)along with several others. `In the next edition of JSLint I will be removing several options... ass, closure, continue, eqeq, newcap, nomen, plusplus, sloppy, stupid, sub.` – ruffin Sep 15 '14 at 15:03
  • 5
    or ```"plusplus" : false``` in .jshintrc – user3751385 May 15 '15 at 09:10
28

To avoid confusion, and possible problems when using minifiers, always wrap parens around the operator and its operand when used together with the same (+ or -).

var i = 0, j = 0;
alert(i++ +j);

This adds i and j (and increments i as a side effect) resulting in 0 being alerted.

But what is someone comes along and moves the space?

var i = 0, j = 0;
alert(i+ ++j);

Now this first increments j, and then adds i to the new value of j, resulting in 1 being alerted.

This could easily be solved by doing

var i = 0, j = 0;
alert((i++) +j); 

Now this cannot be mistaken.

Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
  • 2
    Thanks for explaining. I tried putting the in (e++) instead of e++, but JSLint persists. – KdgDev Jun 08 '10 at 20:13
  • 7
    Ok, then you just need to set `plusplus: false` in your jslint options. That should disable that check. – Sean Kinsey Jun 08 '10 at 21:07
  • 14
    jslint seems to be arbitrarily pedantic about this. How many millions of for loops are clearly written with an `i++`? And somehow we have all survived despite the lack of parentheses surrounding and protecting the increment statement. – Cheeso Aug 23 '11 at 18:48
  • 1
    @Cheeso, it's a big difference between a single expression in the form of `i++` and a compound AdditionExpresion where one of the operands is a unary expression. But this has nothing to do with the lexer, this is about createing concise code where all intent is communicated clearly. – Sean Kinsey Aug 24 '11 at 09:05
  • 1
    @Sean Kinsey the last example will still alert 0, and by reading the code it still is not clear to what the intended purpose was, acutally it seems like the code will increment the i first, but it will not – Paul Scheltema Apr 05 '13 at 11:31
  • @PaulScheltema And that is exactly the point, 0 is what was intended. If you know javascript you know the difference between prefix and postfix operators, so no ambiguity here ;) – Sean Kinsey Apr 05 '13 at 18:41
  • If you have to wrap parens around code to avoid problems with a minifier this suggests a problem. It's better to avoid things that require obscure knowledge if there's a perfectly fine alternative with less chance for error. Another dev could easily come along at a future date and try to "optimize" the code by removing the parens. – whitneyland Nov 24 '17 at 20:13
13

Personally, I prefer to put statements such as i++ on a line by themselves. Including them as part of a larger statement can cause confusion for those who aren't sure what the line's supposed to be doing.

For example, instead of:

value = func(i++ * 3);

I would do this:

value = func(i * 3);
i++;

It also means people don't have to remember how i++ and ++i work, and removes the need to apply quite so many preference rules.

Peter Coulton
  • 54,789
  • 12
  • 54
  • 72
Samir Talwar
  • 14,220
  • 3
  • 41
  • 65
9

The real problem of the ++ operator is that it is an operator with side effects and thus it is totally opposed to the principle of functional programming.

The "functional" way to implement i++ would be i = i + 1 where you explicitly reassign the variable with no side effects and then use it.

The possibility of confusion is that ++ does two things by adding a value AND reassigning it to the variable.

benzonico
  • 10,635
  • 5
  • 42
  • 50
  • even Lisp (as well as Mathematica) has both `(1+ num)` and `(incf 1)` ... because having `++` is mostly about syntax (because it's essentially a syntactic sugar), not about the semantics of use. There's *always* a possibility of confusion; some languages (see above) assume the sanity of the programmer, some (Python, R, MATLAB) don't. It's not for me to decide which are right. Still, JavaScript ain't any more "functional" than current-day C++, C# or Java (lambdas, closures, etc.) –  Jul 18 '17 at 17:48
  • 1
    That's not at all true. `i = i + 1` has the same side effects as `i++` . `i++` is just a shorthand. in `i = i + 1` you mutate the value of i. that's why for example in scala you can only use it with `var` and not `val` to show that you mutate the value. I don't see how `i = i + 1` is more functional than `i++` if both have the same side effects. – Claudiu Creanga Aug 30 '17 at 09:18
  • 1
    @robinCTS `The truth of the matter is that i = i + 1 has no side effect` It has side effects because you mutate the value. How come you can't use it as val if you say there are no side effects? – Claudiu Creanga Oct 04 '17 at 11:27
  • @vaxquis & ClaudiuCreanga Unless I have a complete misunderstanding of what 'side' actually means ;) – robinCTS Oct 04 '17 at 17:58
  • @robinCTS see https://softwareengineering.stackexchange.com/questions/40297/what-is-a-side-effect ; what you say is a (sadly) very common misconception. In FP context, "side effect" is used *exclusively* to describe mutating the state (vs pure functions, which have no s.e. and no mutations of state). As to your example - yet again, you're doing it wrong, because of the reasons I outlined earlier; "don't use assignments/++/-- in complex expressions" is a **very** common guideline, present in virtually any decent IDE. Just turn it on and stop worrying about cases you'll never see in sane code. –  Oct 04 '17 at 18:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155958/discussion-between-vaxquis-and-robincts). –  Oct 04 '17 at 18:08
7

JSLint friendly loop

for (i = 0; i < 10; i += 1) {
    //Do somthing
}
4

Please note that the ++ operator depends on position with respect to the prior/next variable and the newline / semicolon to determine order of operations.

var a = 1;
var b = a++;
console.log(b); // b = 1
console.log(a); // a = 2

var a = 1;
var b = ++a;
console.log(b); // b = 2
console.log(a); // a = 2
3

There is something called a pre-increment: ++i and a post-increment i++ and there is a difference:

var i = 9;
alert(++i); //-> alerts 10

var j = 9;
alert(j++); //-> alerts 9
alert(j);   //-> alerts 10 now, as expected

var k = 9;
alert((k++)); //-> still alerts 9 even with extra parentheses
Paul Scheltema
  • 1,993
  • 15
  • 25