This question already has answers here:
Why avoid increment ("++") and decrement ("--") operators in JavaScript?
(17 answers)
Closed 5 years ago.
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];
}
}
}
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.
Just add /*jslint plusplus: true */ in front of your javascript file.
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.
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.
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.
JSLint friendly loop
for (i = 0; i < 10; i += 1) {
//Do somthing
}
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
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
Related
This question already has answers here:
++someVariable vs. someVariable++ in JavaScript
(7 answers)
Closed 4 years ago.
This is a basic JS question I think, but I just couldn't find an answer that I was satisfied with. I'm learning operators in JavaScript and I can't understand this following postfix example and how it works:
var x = 4;
var y = x++;
For example, when I alert x, it gives me 5. But when I alert y, it gives me 4. And I can't understand the logic behind it.
I understand that, because it's a postfix, x is assigned to y. And y reads just x, without the postfix. But why does then the original x read the postfix instead if I'm applying it to a different var?
If I just did var y = x + 1, the original x would stay unchanged. But that's not the case when I use postfix. Why would I even change the x with this method? Couldn't I just go then var x = 4; x++; ? And not bother changing it via another var?
I apologize if this is too basic and thanks in advance!
It's easier to think of the increment operators as little functions that return something. So x++ is a functions that increments x and returns the original value of x, whereas ++x does the same thing but returns the new value.
This comes in handy from time to time especially in loops where you want precise control of the stopping point. For example, compare:
let i = 0, j = 0;
while (++i < 5) {
console.log(i) // stops at 4
}
while (j++ < 5) {
console.log(j) // stops at 5
}
The difference is because the while loop evaluates one before the increment and the other after.
Similarly in recursive functions you'll often see things like:
function recurse(i) {
if (i == 5) return i
console.log(i)
return recurse(++i)
}
console.log("final: ", recurse(0))
But if you use the postfix return recurse(i++) you get infinite recursion.
Why would I even change the x with this method?
For some funny shortforms like:
const array = [1, 2, 3];
let i = 0;
while(i < array.length) console.log(array[ i++ ]);
Couldn't I just go then var x = 4; x++; ?
Yeah or just prefix, like ++x or just x += 1 which is more appropriate in most cases.
I have looked around, and have not been able to figure out why I'm throwing this error on this simple rotation algorithm. Happens with .push, .shift, .splice. Pls help! (I am aware there are more efficient ways to solve, just want to understand why I can't get these methods to work!)
function rotation(n, d) {
var a = []
for (i = 1; i <= n; i++) {
a += i
};
for (x = 1; x <= d; x++) {
a.push(a[0]);
a.shift();
}
console.log(a)
}
rotation(5, 4)
a += i means a = a + i. + has no special meaning for arrays. By using +, you're coercing to a primitive — a string, in this case — and doing string concatenation. Since then a refers to a string, not an array, it doesn't have array methods.
If you want to add an element, use push, not +:
for(i=1; i <= n; i++){
a.push(i);
}
Also note that semicolons (;) don't go at the end of control-flow statements with blocks attached, and do go at the end of all other statements (for instance, your original a += i, the console.log near the end, etc.).
I'm a bit stumped by the exact order of execution of a particular for loop I'm playing with, in Codepen. Check out these two loops, which both do the same thing:
var a = ['orange','apple'];
for (var i=0; i<2;i++) {
alert(a[i]);
}
for (var j=0, fruit; fruit = a[j++];) {
alert(fruit);
}
You can see this in action here: http://codepen.io/nickbarry/pen/MYNzLP/
The first loop is the standard, vanilla way of writing a for loop. As expected, it alerts "orange", then "apple".
I wrote the second loop using a suggestion from MDN (search for "idiom", here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript ).
It works, but I don't quite understand why. My understanding of for loops, which is obviously incorrect in some way (more than one way?) is that:
* The for loop evaluates the truthiness of the second expression before it runs the first time. So it seems that when the for loop is evaluating the truthiness of the second expression, it should increment j before setting the value of fruit. So the first time through the loop, fruit should equal "apple".
* And the loop should only run once, because after the first time through, when it's evaluating the second expression again to see if it's still true, it should once again increment j before it returns a value to fruit, and since there is no value at index position 2, it should return a falsy result, and exit the loop.
I don't understand what actually IS happening. Does the for loop run once before the second expression is evaluated? But that seems impossible, because if that happened, the alert would alert nothing the first time through, since fruit wouldn't yet have a value.
Also, the author of the MDN article seemed to like the second way of writing the loop - is there a reason that way is better? It uses fewer characters, which is good, I guess. Does skipping the third expression in the for loop save significant time? Or is it just a "it's cool because it's clever" sort of thing?
for (var j=0, fruit; fruit = a[j++];) {
alert(fruit);
}
In pseudocode is equal to:
initialize j = 0 and fruit = undefined
assign fruit = a[j] (j = 0, fruit = 'orange')
j = j + 1 (j = 1)
check fruit for being truthy (true)
alert(fruit) ('orange')
assign fruit = a[j] (j = 1, fruit = 'apple')
j = j + 1 (j = 2)
check fruit for being truthy (true)
alert(fruit) ('apple')
assign fruit = a[j] (j = 2, fruit = undefined)
j = j + 1 (j = 3)
check fruit for being truthy (false)
exit loop
Important note:
The postfix unary ++ operator works as:
We return the current value of the variable
We increment the value of the variable
Does skipping the third expression in the for loop save significant time?
It does not save anything at all
Also, the author of the MDN article seemed to like the second way of writing the loop - is there a reason that way is better?
It's not better in any way. Author just thinks it's cool and author likes to be cool (while they are not).
A for loop is really just a shorthand way of writing a while loop.
e.g. this loop
for(var i = 0, j = 10; i < 10; i++, j++) {
alert(i + ", " + j);
}
is just a shorter way of writing
var i = 0, j = 10;
while(i < 10) {
alert(i + ", " + j);
i++; j++;
}
So that mans this loop
for(var j=0, fruit; fruit = a[j++];) {
alert(fruit);
}
is the same as this
var j = 0, fruit;
while(fruit = a[j++]) {
alert(fruit);
}
You can follow through the order of execution of JavaScript's for loop using SlowmoJS: http://toolness.github.io/slowmo-js/
The homepage already has the for loop loaded into the console for demonstration purposes, but you evaluate the order of operation of any code, as you see fit.
Astonished to find out that a line like this :
$('#TextBox').val(parseInt($('#TextBox').val())++ );
Will not work !
I've done some tests, it plays out to the conclusion that the inline ++ doesn't work (in Javascript as a whole ? Or simply in my example ?).
Here's a test with three pieces of code, it seems that ++ is ok with a variable but not inline.
So, no inline ++ for us in Javascript?
There's nothing particular to jQuery about this. ++ increments a variable. You are trying to increment the return value of a function call.
Q: What does x++ mean?
A: x++ means take the value of x, let's call this n, then set x to be n + 1, then return n.
Q: Why does this fail on a non-variable?
A: Let's try it on something simple, say 3, and see where things go wrong.
Take the value of 3 and call it n, okay, n = 3
Set 3 to be n + 1, so 3 = 3 + 1, 3 = 4 this makes no sense! So if this step can't be done, the ++ operator can't be used.
++ works on variables, not directly on numbers
var c = parseInt($('#TextBox').val());
$('#TextBox').val( ++c );
Change the order from
var x = 0;
var result = x++;
result // 0
To
var x = 0;
var result = ++x;
result // 1
Then it will evaluate ++ before retrieving the value.
Today I came across the following JS:
for (var b = k, d = function (c) {
// function body
}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
Can some please explain what's happening here? I'm confused about the function, normal "for" loop would do:
for(x=0; x<something; x++){
}
This loops appears to follow a different structure:
for(x=0; d = function(c), a = somevar, e = somevar, 0 < c)
Why are there 5 elements in the for loop? Thanks!
for (var b = k, d = function (c) {}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
for(x=0; x<something; x++)
If you map the first for loop with the signature for loop...
The code in bold is the declaration part for different variables that are going to be used inside the for loop.. .. Any number of variables can be declared here...
The second is the check condition...
And the third part is empty
There are not five parts, only three:
The first one contains four variable declarations (b, d, a and e).
The second one contains a comparison (0 < c).
The third one is empty.
Each part is separated by semicolons (;) and the variable declarations are separated by commas ,.
The first part is allowed to contain either an expression or a variable declaration list. For more information, have a look at the specification or the MDN JavaScript documentation:
initialization
An expression (including assignment expressions) or variable declaration. Typically used to initialize a counter variable. This expression may optionally declare new variables with the var keyword. These variables are not local to the loop, i.e. they are in the same scope the for loop is in. The result of this expression is discarded.
Only because for(x=0; x<something; x++) is the most typical form, does not mean others don't exist. Each part can contain an arbitrary expression. For example, a useful way to iterate over all children of a DOM element is the following:
for(var node = element.firstChild; node; node = node.nextSibling) {
}
First, node is initialised with the first child of the element. The second part just tests whether node is not null (you could also write node !== null explicitly) and the third part (executed after the iteration) assigns the next child to node.
Ill explain, but basically this is not good code.
Its not good code because you need to go online just to figure it out.
for (var b = k, d = function (c) {
// function body
}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
is the equivalent of
var b = k,
d = function (c) {
// function body
},
a = b.p,
e = z;
for (; 0 < c; ){
}
for loop parents has three parts
1. Initialization
2. Condition
3. Ending statement
That must all be separated by a ;
except these are all optional in a for loop
for (var init = 0; init < 10; init += 1) {}
same as:
var init = 0;
for (;;) {
if (!(init < 10)) {
break;
}
init += 10;
}
The control variables in a loop can also be a valid expressions as you have in your example.
The first loop you posted is slightly different from the last. The first declares and assigns several variables (one of which is a function), then provides a condition (0<c), then does nothing every iteration. The last seems invalid.
The problem with the first one seems to be only that it does not intialize a c, so unless c is a variable from outside of the scope of the loop that is somehow being changed inside its body, the loop will either not run at all (if c>=0) or it will run forever (if c is indeed less than 0).
for (var b = k, d = function (c) {
// function body
}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
as long as d is not 0 the for loop will run. d is 0 when 0 < c