4

I'm getting two errors in a JS file, both "Unexpected '--'." It's in code for mousewheel scrolling (both times as this.addEventListener( types[--i], handler, false ); ). I've never seen this --i syntax anywhere before. What is it, and how should I correct it to be proper, and make JSLint happier?

(function($) {
var types = ['DOMMouseScroll', 'mousewheel'];
$.event.special.mousewheel = {
    setup: function() {
        var i;
        if ( this.addEventListener ) {
            i = types.length;
            while ( i >= 0 ) {
                this.addEventListener( types[--i], handler, false );
            }
        } else {
            this.onmousewheel = handler;
        }
    },

    teardown: function() {
        if ( this.removeEventListener ) {
            i = types.length;
            while ( i >= 0 ) {
                this.removeEventListener( types[--i], handler, false );
            }
        } else {
            this.onmousewheel = null;
        }
    }
};
Keefer
  • 2,269
  • 7
  • 33
  • 50
  • possible duplicate of [JavaScript Lint inc_dec_within_stmt warning](http://stackoverflow.com/questions/1132001/javascript-lint-inc-dec-within-stmt-warning) – Mark Biek Feb 07 '12 at 20:21
  • 2
    There's a setting that you can use to have JSLint stop being silly about operators like ++ that have existed for decades – Adam Rackis Feb 07 '12 at 20:27
  • 3
    Don't you change your code because of this warning! JSLint is a prick, and will always remain a prick. Also it can be incredibly useful if you are perfecting reusable codes/plugins you want to share but not be ashamed of. – vinczemarton Feb 07 '12 at 20:48
  • 1
    I tend to agree that Crockford is being subjective on this particular check. That said, I don't think he's being silly or a "prick". It is equally subjective to say that he is being so. – JAAulde Feb 08 '12 at 01:13

4 Answers4

6

--n syntax decrements a variable. Slightly more common, that you may have seen is n++, which is similar, but increments a variable.

The -- or the ++ can appear before or after the variable, and there is a subtle difference. When it come before, it alters the value and then returns the altered value. When it comes after, it returns the original value. When using the value directly, this makes a difference.

var i;

// affix
i = 1; console.log(i++, i) // 1 2
i = 1; console.log(i--, i) // 1 0

// prefix
i = 1; console.log(++i, i) // 2 2
i = 1; console.log(--i, i) // 0 0

Note how the value of the prefixed increment or decrement expression returns the same value for i after the operation, where the affix version doesn't.

So, long story short, JSLint doesn't like prefixed increment operators very much. But this should be equivalent:

while ( i >= 0 ) {
  i -= 1;
  this.removeEventListener( types[i], handler, false );
}

By not using the direct result of decrement operation, it ceases to matter how that operator works and what it returns. It's also a bit more explicit, and JSLint likes explicit.

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • Also, in some implementations I believe the prefix is slightly faster. It's a micro-optimization that in the vast majority of cases won't matter, but the use of prefix over postfix (or affix) increment/decrement operators is most likely due to this meaninless reason. Great explanation. – Mattygabe Jul 02 '12 at 12:58
3

JSLint rejects all of the operators --i, i--, ++i and i++.

just put a line with

i -= 1;

before both lines with errors and replace --i with just i, and JSLint should be happy.

--i decreases the variable i by one before executing the surrounding statement. the readability of code using this is worse than code without it. That's the reason why JSLint discourages the use of it.

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
Sirko
  • 72,589
  • 19
  • 149
  • 183
1

Change this:

while ( i >= 0 ) {
    this.addEventListener( types[--i], handler, false );
}

To this:

while ( i >= 0 ) {
    i -= 1;
    this.addEventListener( types[i], handler, false );
}

The -- operator preceding a variable decrements the value of the variable before use, storing the new value into the variable. So --i is a pre-decrement and means "set i to the value of i-1, then proceed with what you were going to do with i". The opposing operation would be a post-decrement (i--) which means "use i as is for current operation, then set it to the value of i-1".

Crockford defaults JSLint to reject this sort of operation because he believes it to be confusing, hard to read, and less maintaiable. You could also go the route of configuring the LINT tool to "Tolerate -- and ++" (LINT property plusplus: true). In your case, though, the adjustment is minimal to the code so the edit is probably preferable.

JAAulde
  • 19,250
  • 5
  • 52
  • 63
1

Change the line to read:

this.addEventListener( types[i -= 1], handler, false );

to make JSLint happy.

See Why avoid increment ("++") and decrement ("--") operators in JavaScript? and post increment vs pre increment - Javascript Optimization (and others by googling "pre and post increment javascript") for what ++ and -- actually do.

Community
  • 1
  • 1
pete
  • 24,141
  • 4
  • 37
  • 51
  • 1
    It seems a little bizarre that JSLint would reject the well understood increment/decrement operators yet not also insist that the `i-=1` go on a line on its own - in my opinion `types[i-=1]` is _less_ readable... – nnnnnn Feb 07 '12 at 20:40