Proper Placement of the Increment Operator

I admit that there are certain nuances to programming that I’ve never fully been able to wrap my brain around. One in particular is the proper placement of the increment operator:

( for var i = 0; i < 10; i++ )

versus…

( for var i = 0; i < 10; ++i )

I was certainly aware that there’s a difference… but never fully comprehended what that difference was. And it never seemed to be a big deal, as placing the increment operator after the operand always seemed to work for me.

…until today, that is.

The actual code I was working on isn’t terribly interesting, so let’s geek it up a bit and say I have an array as follows:

var xArray = [ "Cyclops", "Beast", "Iceman", "Marvel Girl", "Professor X" ];

Assuming I have navigation links to cycle thru the array:

<a class="navigation" id="go-prev">Prev</a>
<a class="navigation" id="go-next">Next</a>

… and the following code to get the next or previous element:

$( document ).ready( function() {
	$( '.navigation' ).click( function( e ) {
		e.stopPropagation();
		e.preventDefault();

		var nextRecord = ( $( this ).attr( 'id' ) == "go-next" ) ? xArray[ currentPosition++ ] : xArray[ currentPosition-- ];

		console.log( nextRecord );
	};
});

Breaking that down, if I click on the “Previous” link, I want to go to the previous element in the array. If I click on the “Next” link, I want to go to the next element in the array. And whichever way I happen to go, I want to assign the result to the variable “nextRecord”. To keep things simple, I’m just going to log that result to the console to verify that I get the expected result.

Let’s assume that the current value of “currentPosition” (a global variable) is 3. That means I’m on Marvel Girl (yes, I know). “Previous” should bring me to “Iceman”, and “Next” should bring me to “Professor X”.

But when I click “Next”, I’m not on Professor X, as I expected to be. I’m still on Marvel Girl (yes, I know). I hit refresh and try going the other way. Hitting “Previous” should put me on Iceman, but the console indicates that yes… I’m still on Marvel Girl.

The code seemed pretty sound. If I click “Next”, increment the current position (currentPosition++), and if I click “Previous”, decrement the current position (currentPosition--). Try as I might, I couldn’t get off of Marvel Girl (I’ll let that go now).

My next course of action is to start logging more data to the console. First I added a console.log of currentPosition, to ensure that it’s being incremented/decremented as expected:

$( document ).ready( function() {
	$( '.navigation' ).click( function( e ) {
		e.stopPropagation();
		e.preventDefault();

		var nextRecord = ( $( this ).attr( 'id' ) == "go-next" ) ? xArray[ currentPosition++ ] : xArray[ currentPosition-- ];

		console.log( nextRecord );
		console.log( currentPosition );
	};
});

Again, with the initial value of “currentPosition” being 3, I click “Previous”. I expect to see “Iceman” and “2″ in the console. But instead I see “Marvel Girl” and “2″.

Now wait a minute… if “currentPosition” is, in fact, 2… which is what we expect it to be, then why is the value of “nextRecord” not “Iceman”? My next step was to actually log the array to the console, just to make sure it wasn’t somehow being altered. It wasn’t. I knew it wasn’t, but it was a desperation move… like when you lose your keys, and you look everywhere, so you check the freezer. You know they’re not in the freezer, but you still have to check, just to be sure. That’s not just me, right?

I’d like nothing more than to tell you that this is where I had a “light bulb” moment, and knew that the solution to what ails me would be putting the increment and decrement operators before the operands. I mean, that’s exactly what I did… but not because I knew it was the answer… but rather because I was still desperate. The equivalent of checking the shower to make sure your keys aren’t in there.

But I’ll be damned. It worked. New code:

$( document ).ready( function() {
	$( '.navigation' ).click( function( e ) {
		e.stopPropagation();
		e.preventDefault();

		var nextRecord = ( $( this ).attr( 'id' ) == "go-next" ) ? xArray[ ++currentPosition ] : xArray[ --currentPosition ];

		console.log( nextRecord );
		console.log( currentPosition );
	};
});

Note line 6. Almost the same, but not really. And now that I knew what the answer was, it was time to understand why it was the answer. I hit Google, and I think this question at Stack Overflow sums up the answer pretty nicely.

Placing the increment operator after the operand (i++) evaluates the variable, and then increments it. So in my original code, with the value of currentPosition starting off at 3, xArray[ currentPosition++ ] evaluated to xArray[ 3 ]… and then currentPosition was incremented to 4. This is why I saw the correct value for “currentPosition” in the console, and the incorrect value for “nextRecord”.

Placing the increment operator before the operand (++i), increments the variable and then evaluates it. So in my original code, with the value of currentPosition starting off at 3, xArray[ ++currentPosition ] evaluated (correctly) to xArray[ 4 ].

I remain hopeful that there’s at least one other person out there who hasn’t yet quite grokked the difference in the placement of these operators. Whoever and wherever you are… this is for you.