space and/or perfomance wise, what would be a more efficient way to add strings, in the case of having many string literals concatenated together, in Javascript?
x += y;
OR
x + y;
I've been pondering about this for a while. Of course for a case where there are only two strings being concatenated together there would be virtually no difference, but what about cases where a CSS or html document is being structured inside the JS, or a huge XML, for whatever reason?
string += " classA {}";
...
.....
string += "classX {}";
VS
string + "classA {}" +
...
.....
+ "classX {}";
Sorry if this sounds like a basic question, but I had a similar problem when I had to code an XML parser in Java and realized the usage of StringBuilder. Not sure how this translates to JavaSript.
Do you want to modify x? More specifically, does it matter if x gets modified?
x + y on its own doesn't do anything unless used as an argument or captured to a variable. let z = x + y does, as does f(x + y).
x += y is equivalent to x = x + y and so modifies x, which may or may not be what you want.
Normally if your intent is to "append to x" and save the result then you'd say x += y.
If your intent is to use the combined x and y in some other place, such as f(x + y), then that's appropriate. Here f(x += y) sends mixed messages, as it's not clear why you'd be appending and calling.
It's purely your own choice. How you're comfortable doing. Doesn't have any specific standard to it. I could argue that when using x += y when you have to use multiple statements between the string declaration & modification. However, again it still comes down to your own choice.
I am trying to build a function that takes a price with 2 decimal points and finds the next highest palindrome. I know there are several other ways to approach this, but I am curious why my method is not working. I am new to JS so this might be a simple one. Any advice would be great.
I broke it into smaller chunks with explanations of what I want it to do below:
var ask = prompt("Enter a price");
var reverseIt = function (x) {
x = (parseFloat(x) * 100).toString();
for (var i = (x.length - 1); i >= 0; i--) {
x.substr(i, 1);
}
return
};
The reverseIt function takes an argument removes the decimal (* 100) and reverses the number.
var removeDec = function (j) {
return (parseFloat(j) * 100).toString();
}
The removeDec function takes an argument, removes the decimal point (* 100), and converts it back to a string. Is this redundant for comparing two "number" strings? Should I use the Number() and String() functions instead?
var findDrome = function (i) {
for (var i; removeDec(i) != reverseIt(i); i += (1 / 100)) {
if ((removeDec(i) + 1).toString() == reverseIt(i)) {
document.write(i + (1 / 100));
}
} return
};
findDrome(ask);
The findDrome function takes the ask prompt at the start as an argument. If the number without a decimal doesn't match the reverse without a decimal, then increments it by 0.01. Right before the loop ends, I wanted it to check if the number prior +1 (since it is * 100) is equal to the reverse and if so write the next number.
It wasn't working, so I tried adding parseFloat and toString to specify stricter/more explicit conversions. I also used the loose equality operators, but it's still not working.
My questions: Is this a conversion or syntactical problem or can you not compare the output of 2 functions? Should I instead compare 2 variables and if so how do I assign the for loop in the reverseIt function to a variable?
Your program has a number of issues. First, your reverseIt function never returns a reversed value. The variable x is passed in but it's never updated in the for loop - x.substr() creates a new string instance but it's never assigned back to x so its value never changes. As it is, your for loop in findDrome goes infinite since reverseIt returns undefined.
Another - possible - problem is that you're incrementing a floating-point number by 1/100 but floating point values have no exact representation. I don't know if this is actually affecting your code (since it currently never returns a proper value) but it's something you may have to worry about. This would likely affect parseFloat (which may return a slighly different floating-point value than the string it parses).
Using toFixed() would truncate the number to 2 decimal digits. You could then turn the number to a string and remove the decimal dot character, rather than converting the number back and forth between string and number.
You may want to read up on floating-point arithmetic (if you're not already familiar with it).
As a last comment, you should never, ever rely on Javascript terminating your statements - you should always use ; to terminate a statement like in other proper C-style languages. Leaving out ;-s (even if Javascript lets you get away with it) is considered very poor practice.
I figured it out thanks to the help above! Here is how the fixed program works:
var ask = prompt("Enter a price to find the next palindromic price");
var removeDec = function (j) {
return parseInt(j * 100);
};
var c = removeDec(ask);
This prompts a price and multiplies it by 100 to remove the decimal point and avoid floating point arithmetic. The parseInt removes any decimals smaller than the hundredths place.
var reverseIt = function (x) {
var a = ""
x = x.toString();
for (var i = (x.length - 1); i >= 0; i--) {
a = (a + String(x.substr(i, 1)));
}
return Number(a);
};
var b = reverseIt(c);
The reverseIt function takes an argument, converts it to string and adds each character in reverse to an empty string (a=""). Var a is then returned as a number. The empty string is important for storing the reverse number and is a big reason why my code wasn't working before.
var e = Math.pow(10, (String(c).length - 1));
Var e was added to take into account varying place values to left side of the decimal. Later this helps check if a number is equal to its reverse by adding a 1 to both sides of the number. Var e counts the length of var c (entered value with decimal removed) and finds the appropriate power of 10 to add later. So if you entered 14.40 * 100 then later it will check if 1440 + 1 is equal to 0441 + 1000.. or 10^3. This test is important later in order to exit the loop. This is where my code was failing before because I didn't take adding a number to the reverse into account and I was trying to add decimals which aren't as predictable.
if (c == b) {
document.write("$" + (c / 100) + "... This price is already palindrome!")
} else {
for (c; c !== b; c++) {
b = reverseIt(c);
if ((c + 1) == (b + e)) {
document.write("The next palindromic price is $" + ((Number(c) + 1) / 100));
break;
}
}
}
Here, If the original number and it's reverse are not equal then a loop begins that increments the value by 1 until the entered number + 1 is equal to the reversed number + e. So effectively the loop finds the number right before the loop ends, writes it and then breaks out of the loop. This palindrome finder seems to work smoothly with values big and small, no matter where you put the decimal point. Glad I got it working... it was a great learning experience figuring it out!
I wouldn't run this if I were you:
Javascript:
(function() {
var a = 1,
b = a,
c = b,
d = 1,
e = 1;
while ( d != 0 && e != 0) {
b = Math.sqrt(a*a+a*a);
c = 2*a-b;
e = b%1;
f = c%1;
document.write(a);
a++;
}
document.write('a = ' + a);
document.write('b = ' + b);
document.write('c = ' + c);
})();
Yeah basically I want to calculate the same equation over and over again until all three are integers with Javascript and then print them out. Please know that up until recently I only used jQuery.
This seems to just repeat infinitely though I find it weird that it does not print a while calculating, not sure if thats how the javascript while loop works.
Also, why can't i use Math.sqrt(2a^2) to calculate B?
It never ends because d will never equal 0. You initialize it to 1 and never reassign it. You're also using an undeclared variable f. Is that supposed to be d?
I'd also suggest using console.log instead of document.write. It's flushed more frequently than the DOM and typically has much better logging capabilities. Check out the WebKit Inspector (Safari and Chrome), Firebug (Firefox), or the F12 Developer Tools (IE).
As PaulP.R.O. pointed out, your desired syntax for exponentiation is invalid JavaScript syntax. You could write it like this if you wanted to:
b = Math.sqrt(2 * Math.pow(a, 2));
Math.sqrt(2a^2) doesn't work because:
1) You must be explicit in Javascript when you want multiplication by using *. 2a doesn't mean 2*a.
2) ^ has a different meaning in Javascript than exponentiation. It means Bitwise XOR
Both those are true in many other programming languages as well. Math.sqrt(2*a*a) would work for you.
Your loop doesn't exit because d != 0 is always going to be true since you never modify d from it's original value of 1.
I'm not sure what you are trying to do with b%1 and c%, but any integer mod 1 will give you 0.
Nothing is written to the screen because your loop doesn't ever stop executing and therefore doesn't give a web browser a chance to render anything.
I'm studying for an exam on JavaScript at the moment. I've also got a little knowledge of C and Perl so I'm familiar with prefix and postfix operators in all three languages.
I did an online practice exam for it and one mistake I made was in evaluating the following code:
var x = 10;
x += x--;
Now, I thought it would evaluate to 19 because it would be 10 + 10, then subtract 1 to make 9. But the feedback I got was that it was wrong and it actually evaluates to 20. I thought that sounded a bit suspicious so I tested it out in an HTML document, and it came out with 20 again. I then tried the equivalents in C and Perl and both evaluated to 19.
Can anyone explain to me why JavaScript evaluates the answer as 20 when other languages evaluate it to 19? The answer I got from the test wasn't too clear to me:
The increment ++
and decrement -- operators can be placed
either before or after an operand. If the increment or decrement
operator is placed before the operand, the operation occurs immediately.
If the increment or decrement operator is placed after the operand, the
change in the operand's value is not apparent until the next time the
operand is accessed in the program. Thus the expression x += x-- is equivalent to x = x +
10 which evaluates to 20.
Expanding the statement
x += x--;
to the more verbose JS code
x = x + (function(){ var tmp = x; x = x - 1; return tmp; })();
the result makes perfect sense, as it will evaluate to
x = 10 + (function(){ var tmp = 10; x = 10 - 1; return tmp; })();
which is 20. Keep in mind that JS evaluates expressions left-to-right, including compound assignments, ie the value of x is cached before executing x--.
You could also think of it this way: Assuming left-to-right evaluation order, JS parses the assignment as
x := x + x--
whereas Perl will use
x := x-- + x
I don't see any convincing arguments for or against either choice, so it's just bad luck that different languages behave differently.
In C/C++, every variable can only be changed once in every statement (I think the exact terminology is: only once between two code points, but I'm not sure).
If you write
x += x--;
you are changing the value of x twice:
you are decrementing x using the postfix -- operator
you are setting the value of x using the assignment
Although you can write this and the compiler won't complain about it (not sure, you may want to check the different warning levels), the outcome is undefined and can be different in every compiler.
Basically, the value of x is decemented after assignment. This example might make it clearer (run in Firebug console)
var x = y =10;
x += y--;
console.log(x , y); // outputs 20 9
In C, the line
x += x--;
is undefined behaviour. It seems like your particular compiler is treating it like:
oldx = x--;
x = x + oldx
However, the ECMAScript specification does specify op= - and it gets the value of the left-hand-side before evaluating the right-hand-side.
So it would be equivalent to:
oldx = x--;
x = oldx + oldx
One of the tips for jslint tool is:
++ and --
The ++ (increment) and -- (decrement)
operators have been known to contribute to bad code by
encouraging excessive trickiness. They
are second only to faulty architecture
in enabling to viruses and other
security menaces. There is a plusplus
option that prohibits the use of these
operators.
I know that PHP constructs like $foo[$bar++] may easily result in off-by-one errors, but I couldn't figure out a better way to control the loop than a:
while( a < 10 ) do { /* foo */ a++; }
or
for (var i=0; i<10; i++) { /* foo */ }
Is the jslint highlighting them because there are some similar languages that lack the "++" and "--" syntax or handle it differently, or are there other rationales for avoiding "++" and "--" that I might be missing?
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.
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.
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.
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
The "pre" and "post" nature of increment and decrement operators can tend to be confusing for those who are not familiar with them; that's one way in which they can be tricky.
Consider the following code
int a[10];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
int i = 0;
a[i++] = i++;
a[i++] = i++;
a[i++] = i++;
since i++ gets evaluated twice the output is
(from vs2005 debugger)
[0] 0 int
[1] 0 int
[2] 2 int
[3] 0 int
[4] 4 int
Now consider the following code :
int a[10];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
int i = 0;
a[++i] = ++i;
a[++i] = ++i;
a[++i] = ++i;
Notice that the output is the same. Now you might think that ++i and i++ are the same. They are not
[0] 0 int
[1] 0 int
[2] 2 int
[3] 0 int
[4] 4 int
Finally consider this code
int a[10];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
int i = 0;
a[++i] = i++;
a[++i] = i++;
a[++i] = i++;
The output is now :
[0] 0 int
[1] 1 int
[2] 0 int
[3] 3 int
[4] 0 int
[5] 5 int
So they are not the same, mixing both result in not so intuitive behavior. I think that for loops are ok with ++, but watch out when you have multiple ++ symbols on the same line or same instruction
In my view, "Explicit is always better than implicit." Because at some point, you may got confused with this increments statement y+ = x++ + ++y. A good programmer always makes his or her code more readable.
I've been watching Douglas Crockford's video on this and his explanation for not using increment and decrement is that
It has been used in the past in other languages to break the bounds of arrays and cause all manners of badness and
That it is more confusing and inexperienced JS developers don't know exactly what it does.
Firstly arrays in JavaScript are dynamically sized and so, forgive me if I'm wrong, it is not possible to break the bounds of an array and access data that shouldn't be accessed using this method in JavaScript.
Secondly, should we avoid things that are complicated, surely the problem is not that we have this facility but the problem is that there are developers out there that claim to do JavaScript but don't know how these operators work?? It is simple enough. value++, give me the current value and after the expression add one to it, ++value, increment the value before giving me it.
Expressions like a ++ + ++ b, are simple to work out if you just remember the above.
var a = 1, b = 1, c;
c = a ++ + ++ b;
// c = 1 + 2 = 3;
// a = 2 (equals two after the expression is finished);
// b = 2;
I suppose you've just got to remember who has to read through the code, if you have a team that knows JS inside out then you don't need to worry. If not then comment it, write it differently, etc. Do what you got to do. I don't think increment and decrement is inherently bad or bug generating, or vulnerability creating, maybe just less readable depending on your audience.
Btw, I think Douglas Crockford is a legend anyway, but I think he's caused a lot of scare over an operator that didn't deserve it.
I live to be proven wrong though...
The most important rationale for avoiding ++ or -- is that the operators return values and cause side effects at the same time, making it harder to reason about the code.
For efficiency's sake, I prefer:
++i when not using the return value (no temporary)
i++ when using the return value (no pipeline stall)
I am a fan of Mr. Crockford, but in this case I have to disagree. ++i is 25% less text to parse than i+=1 and arguably clearer.
Another example, more simple than some others with simple return of incremented value:
function testIncrement1(x) {
return x++;
}
function testIncrement2(x) {
return ++x;
}
function testIncrement3(x) {
return x += 1;
}
console.log(testIncrement1(0)); // 0
console.log(testIncrement2(0)); // 1
console.log(testIncrement3(0)); // 1
As you can see, no post-increment/decrement should be used at return statement, if you want this operator to influence the result. But return doesn't "catch" post-increment/decrement operators:
function closureIncrementTest() {
var x = 0;
function postIncrementX() {
return x++;
}
var y = postIncrementX();
console.log(x); // 1
}
I think programmers should be competent in the language they are using; use it clearly; and use it well. I don't think they should artificially cripple the language they are using. I speak from experience. I once worked literally next door to a Cobol shop where they didn't use ELSE 'because it was too complicated'. Reductio ad absurdam.
In my experience, ++i or i++ has never caused confusion other than when first learning about how the operator works. It is essential for the most basic for loops and while loops that are taught by any highschool or college course taught in languages where you can use the operator. I personally find doing something like what is below to look and read better than something with a++ being on a separate line.
while ( a < 10 ){
array[a++] = val
}
In the end it is a style preference and not anything more, what is more important is that when you do this in your code you stay consistent so that others working on the same code can follow and not have to process the same functionality in different ways.
Also, Crockford seems to use i-=1, which I find to be harder to read than --i or i--
As mentioned in some of the existing answers (which annoyingly I'm unable to comment on), the problem is that x++ ++x evaluate to different values (before vs after the increment), which is not obvious and can be very confusing - if that value is used. cdmckay suggests quite wisely to allow use of increment operator, but only in a way that the returned value is not used, e.g. on its own line. I would also include the standard use within a for loop (but only in the third statement, whose return value is not used). I can't think of another example. Having been "burnt" myself, I would recommend the same guideline for other languages as well.
I disagree with the claim that this over-strictness is due to a lot of JS programmers being inexperienced. This is the exact kind of writing typical of "overly-clever" programmers, and I'm sure it's much more common in more traditional languages and with JS developers who have a background in such languages.
My 2cents is that they should be avoided in two cases:
1) When you have a variable that is used in many rows and you increase/decrease it on the first statement that uses it (or last, or, even worse, in the middle):
// It's Java, but applies to Js too
vi = list.get ( ++i );
vi1 = list.get ( i + 1 )
out.println ( "Processing values: " + vi + ", " + vi1 )
if ( i < list.size () - 1 ) ...
In examples like this, you can easily miss that the variable is auto-incremented/decremented or even remove the first statement. In other words, use it only in very short blocks or where the variable appears in the block on just a couple of close statements.
2) In case of multiple ++ and -- about the same variable in the same statement. It's very hard to remember what happens in cases like this:
result = ( ++x - --x ) * x++;
Exams and professional tests asks about examples like above and indeed I've stumbled upon this question while looking for documentation about one of them, but in real life one shouldn't be forced to think so much about a single line of code.
Is Fortran a C-like language? It has neither ++ nor --. Here is how you write a loop:
integer i, n, sum
sum = 0
do 10 i = 1, n
sum = sum + i
write(*,*) 'i =', i
write(*,*) 'sum =', sum
10 continue
The index element i is incremented by the language rules each time through the loop. If you want to increment by something other than 1, count backwards by two for instance, the syntax is ...
integer i
do 20 i = 10, 1, -2
write(*,*) 'i =', i
20 continue
Is Python C-like? It uses range and list comprehensions and other syntaxes to bypass the need for incrementing an index:
print range(10,1,-2) # prints [10,8.6.4.2]
[x*x for x in range(1,10)] # returns [1,4,9,16 ... ]
So based on this rudimentary exploration of exactly two alternatives, language designers may avoid ++ and -- by anticipating use cases and providing an alternate syntax.
Are Fortran and Python notably less of a bug magnet than procedural languages which have ++ and --? I have no evidence.
I claim that Fortran and Python are C-like because I have never met someone fluent in C who could not with 90% accuracy guess correctly the intent of non-obfuscated Fortran or Python.
The operators mean different things when used as prefixes versus suffixes, which can cause hard-to-find bugs. Consider the following example, using bubbleSort:
function bubbleSort(array) {
if(array.length === 1) return array;
let end = array.length - 2;
do {
for (let i = 0; i < array.length; i += 1) {
if (array[i] > array[i + 1]) {
swap(array, i, i + 1);
}
}
} while (end--);
}
bubbleSort([6,5]);
Let's imagine in the course of running our program, we pass a two-item value into our sort function. The code runs fine as-is: the "do/while" loop first executes before reaching the condition. However, the program sees that end is falsy and exits the loop before decrementing the variable.
Now consider the following code, where the -- symbol is used as a prefix, rather than a suffix. This code will enter an infinite loop:
function bubbleSort(array) {
if(array.length === 1) return array;
let end = array.length - 2;
do {
for (let i = 0; i < array.length; i += 1) {
if (array[i] > array[i + 1]) {
swap(array, i, i + 1);
}
}
} while (--end);
}
bubbleSort([6,5]);
Now when we hit the while condition, we decrement the end value before checking it. This returns -1, which in Javascript, is a truthy value.
I don't have a strong opinion on their use one way or the other, but I just wanted to show how they can cause real bugs when used carelessly.
Argument for ++ is that ++ is not applicable for strings which will cause TypeError, which is almost always preferable.