Why avoid increment ("++") and decrement ("--") operators in JavaScript?
Solution 1:
My view is to always use ++ and -- by themselves on a single line, as in:
i++;
array[i] = foo;
instead of
array[++i] = foo;
Anything beyond that can be confusing to some programmers and is just not worth it in my view. For loops are an exception, as the use of the increment operator is idiomatic and thus always clear.
Solution 2:
I'm frankly confused by that advice. Part of me wonders if it has more to do with a lack of experience (perceived or actual) with javascript coders.
I can see how someone just "hacking" away at some sample code could make an innocent mistake with ++ and --, but I don't see why an experienced professional would avoid them.
Solution 3:
There is a history in C of doing things like:
while (*a++ = *b++);
to copy a string, perhaps this is the source of the excessive trickery he is referring to.
And there's always the question of what
++i = i++;
or
i = i++ + ++i;
actually do. It's defined in some languages, and in other's there's no guarantee what will happen.
Those examples aside, I don't think there's anything more idiomatic than a for loop that uses ++
to increment. In some cases you could get away with a foreach loop, or a while loop that checked a different condtion. But contorting your code to try and avoid using incrementing is ridiculous.
Solution 4:
If you read JavaScript The Good Parts, you'll see that Crockford's replacement for i++ in a for loop is i+=1 (not i=i+1). That's pretty clean and readable, and is less likely to morph into something "tricky."
Crockford made disallowing autoincrement and autodecrement an option in jsLint. You choose whether to follow the advice or not.
My own personal rule is to not do anything combined with autoincrement or autodecrement.
I've learned from years of experience in C that I don't get buffer overruns (or array index out of bounds) if I keep use of it simple. But I've discovered that I do get buffer overruns if I fall into the "excessively tricky" practice of doing other things in the same statement.
So, for my own rules, the use of i++ as the increment in a for loop is fine.
Solution 5:
In a loop it's harmless, but in an assignment statement it can lead to unexpected results:
var x = 5;
var y = x++; // y is now 5 and x is 6
var z = ++x; // z is now 7 and x is 7
Whitespace between the variable and the operator can lead to unexpected results as well:
a = b = c = 1; a ++ ; b -- ; c; console.log('a:', a, 'b:', b, 'c:', c)
In a closure, unexpected results can be an issue as well:
var foobar = function(i){var count = count || i; return function(){return count++;}}
baz = foobar(1);
baz(); //1
baz(); //2
var alphabeta = function(i){var count = count || i; return function(){return ++count;}}
omega = alphabeta(1);
omega(); //2
omega(); //3
And it triggers automatic semicolon insertion after a newline:
var foo = 1, bar = 2, baz = 3, alpha = 4, beta = 5, delta = alpha
++beta; //delta is 4, alpha is 4, beta is 6
preincrement/postincrement confusion can produce off-by-one errors that are extremely difficult to diagnose. Fortunately, they are also complete unnecessary. There are better ways to add 1 to a variable.
References
- JSLint Help: Increment and Decrement Operators