In theory, using a post-increment operator may produce a temporary. In practice, JavaScript compilers are smart enough to avoid that, especially in such trivial case.
For example, let's consider that sample code:
sh$ cat test.js function preInc(){ for(i=0; i < 10; ++i) console.log(i); } function postInc(){ for(i=0; i < 10; i++) console.log(i); } // force lazy compilation preInc(); postInc();
In that case, the V8 compiler in NodeJS produces exactly the same bytecode (look esp. at opcodes 39-44 for the increment):
sh$ node --version v8.9.4 sh$ node --print-bytecode test.js | sed -nEe '/(pre|post)Inc/,/^\[/p' [generating bytecode for function: preInc] Parameter count 1 Frame size 24 77 E> 0x1d4ea44cdad6 @ 0 : 91 StackCheck 87 S> 0x1d4ea44cdad7 @ 1 : 02 LdaZero 88 E> 0x1d4ea44cdad8 @ 2 : 0c 00 03 StaGlobalSloppy [0], [3] 94 S> 0x1d4ea44cdadb @ 5 : 0a 00 05 LdaGlobal [0], [5] 0x1d4ea44cdade @ 8 : 1e fa Star r0 0x1d4ea44cdae0 @ 10 : 03 0a LdaSmi [10] 94 E> 0x1d4ea44cdae2 @ 12 : 5b fa 07 TestLessThan r0, [7] 0x1d4ea44cdae5 @ 15 : 86 23 JumpIfFalse [35] (0x1d4ea44cdb08 @ 50) 83 E> 0x1d4ea44cdae7 @ 17 : 91 StackCheck 109 S> 0x1d4ea44cdae8 @ 18 : 0a 01 0d LdaGlobal [1], [13] 0x1d4ea44cdaeb @ 21 : 1e f9 Star r1 117 E> 0x1d4ea44cdaed @ 23 : 20 f9 02 0f LdaNamedProperty r1, [2], [15] 0x1d4ea44cdaf1 @ 27 : 1e fa Star r0 121 E> 0x1d4ea44cdaf3 @ 29 : 0a 00 05 LdaGlobal [0], [5] 0x1d4ea44cdaf6 @ 32 : 1e f8 Star r2 117 E> 0x1d4ea44cdaf8 @ 34 : 4c fa f9 f8 0b CallProperty1 r0, r1, r2, [11] 102 S> 0x1d4ea44cdafd @ 39 : 0a 00 05 LdaGlobal [0], [5] 0x1d4ea44cdb00 @ 42 : 41 0a Inc [10] 102 E> 0x1d4ea44cdb02 @ 44 : 0c 00 08 StaGlobalSloppy [0], [8] 0x1d4ea44cdb05 @ 47 : 77 2a 00 JumpLoop [42], [0] (0x1d4ea44cdadb @ 5) 0x1d4ea44cdb08 @ 50 : 04 LdaUndefined 125 S> 0x1d4ea44cdb09 @ 51 : 95 Return Constant pool (size = 3) Handler Table (size = 16) [generating bytecode for function: get] [generating bytecode for function: postInc] Parameter count 1 Frame size 24 144 E> 0x1d4ea44d821e @ 0 : 91 StackCheck 154 S> 0x1d4ea44d821f @ 1 : 02 LdaZero 155 E> 0x1d4ea44d8220 @ 2 : 0c 00 03 StaGlobalSloppy [0], [3] 161 S> 0x1d4ea44d8223 @ 5 : 0a 00 05 LdaGlobal [0], [5] 0x1d4ea44d8226 @ 8 : 1e fa Star r0 0x1d4ea44d8228 @ 10 : 03 0a LdaSmi [10] 161 E> 0x1d4ea44d822a @ 12 : 5b fa 07 TestLessThan r0, [7] 0x1d4ea44d822d @ 15 : 86 23 JumpIfFalse [35] (0x1d4ea44d8250 @ 50) 150 E> 0x1d4ea44d822f @ 17 : 91 StackCheck 176 S> 0x1d4ea44d8230 @ 18 : 0a 01 0d LdaGlobal [1], [13] 0x1d4ea44d8233 @ 21 : 1e f9 Star r1 184 E> 0x1d4ea44d8235 @ 23 : 20 f9 02 0f LdaNamedProperty r1, [2], [15] 0x1d4ea44d8239 @ 27 : 1e fa Star r0 188 E> 0x1d4ea44d823b @ 29 : 0a 00 05 LdaGlobal [0], [5] 0x1d4ea44d823e @ 32 : 1e f8 Star r2 184 E> 0x1d4ea44d8240 @ 34 : 4c fa f9 f8 0b CallProperty1 r0, r1, r2, [11] 168 S> 0x1d4ea44d8245 @ 39 : 0a 00 05 LdaGlobal [0], [5] 0x1d4ea44d8248 @ 42 : 41 0a Inc [10] 168 E> 0x1d4ea44d824a @ 44 : 0c 00 08 StaGlobalSloppy [0], [8] 0x1d4ea44d824d @ 47 : 77 2a 00 JumpLoop [42], [0] (0x1d4ea44d8223 @ 5) 0x1d4ea44d8250 @ 50 : 04 LdaUndefined 192 S> 0x1d4ea44d8251 @ 51 : 95 Return Constant pool (size = 3) Handler Table (size = 16)
Of course, other JavaScript compilers/interpreters may do otherwise, but this is doubtful.
As the last word, for what it worth, I nevertheless consider as a best practice to use pre-increment when possible: since I frequently switch languages, I prefer using the syntax with the correct semantic for what I want, instead of relying on compiler smartness. For example, modern C compilers won't make any difference either. But in C++, this can have a significant impact with overloaded operator++.