This question already has answers here:
How does += (plus equal) work?
(14 answers)
Closed 5 years ago.
I was writing some javascript code and instead of writing $("p").append(a +", "); i mistyped it as $("p").append(a +=", ");.
After i ran the script the result was quite peculiar. I have created this Fiddle. Click on the button 3,4 times and the result would be something like this : 0, 0, , 0, , , 0, , , ,.
As I am a beginner in javascript maybe i don't know some syntax which is causing this behaviour. Also i wasn't able to find any references to a similar problem anywhere. I want to understand how this is happening.
For every click the value of a changes.
", " is added every time the button is clicked. Since you set a to 0 only at the beginning it keeps on getting longer.
This is caused because of +=.
Writing a += ", " is equivalent of writing a = a + ", ".
a += ", " is the same as a = a + ", ". So every time you click it, a is being modified to have another ", " at the end of it.
a += ", " is the same as a = a + ", "
Basically what is happening is this. You start with the number 0. When you hit the button the first time, 0 becomes the string "0,", when you hit it a second time, you're saying "to the string 0, add the result of concatinating the string 0, and ," which gives us a string of 0,0,, ("0," + ("0," +",")), every time you click the button, the operation is repeated
Everytime you hit the button, you are adding a comma and a space to the variable a.
+= is shorthand for a = a + ', '
Your mistype is equivalent to
a = a + ", ";
$("p").append(a);
That is you are repeatedly concatenating ", " to a.
Related
Here's my fiddle: http://jsfiddle.net/bzoyc64m/
What I'm trying to achieve:
I want the images to fade in and out, right now, it's half working. The initial fades are fine, but when it comes to the second part it just doesn't seem to work.
So if $('.img-' + i + ' .active[rel="1"]') - remove the active class and fade out AND then fade in the next img and add active class - This works
The next stage is the issue - if $('.img-' + i + ' .active[rel="2"]') do the exact same, but for the previous banner. -This doesn't work
Here's my if statement, where I think I'm doing something wrong. I have no idea what though!!
if($('.img-' + i + ' .active[rel="1"]')) {
console.log("1");
$('.img-' + i + ' .active[rel="1"]').fadeOut().removeClass('active').next('img').fadeIn().addClass('active');
}
else if($('.img-' + i + ' .active[rel="2"]')) {
console.log("2");
$('.img-' + i + ' .active[rel="2"]').fadeOut().removeClass('active').prev('img').fadeIn().addClass('active');
}
Also - Out of interest. my i is a random number. Is there any way to prevent that from being the same number twice in a row? So for example, prevent it from doing something like this: 1, 2, 5, 4, 4, 4, 2, 3.
Thanks for any help, it's really appreciated!
The problem is in your if statement. The statement if($('.img-' + i + ' .active[rel="1"]')) {} is always executed. Even though $(selector) does not matches any DOM element, it returns an empty array, which is regarded as true.
if ([])
alert("Empty array is true");
This will show the alert, even if the array is empty. You could check the length of jQuery array instead:
if($('.img-' + i + ' .active[rel="1"]').length>0) {
...
}
For the second part of your question, you can use a shuffling algorithm
How to randomize (shuffle) a JavaScript array?
How can I shuffle an array?
After you consume all indexes, generate a new shuffle. You should pay attention the boundary condition though. The last number of previous shuffle may be equal to the first number of current shuffle.
var reset = function ()
{
var p = parseFloat($("#IA").val());
var q = parseFloat($("#IB").val());
var m = parseFloat($("#CGCD").val());
var aR = [];
aR += ["GCD(" + p + "," + q + ")=" + m];
document.getElementById("PGCD").innerHTML = aR + "\n";
document.getElementById("IA-error").innerHTML="";
document.getElementById("IB-error").innerHTML="";
$("#IA").focus();
};
The code above is only for a 'reset' function, a part of additional code (not present), the purpose which is to find the Greatest Common Denominator, GCD.
My 'reset' function is connected to a button, #reset, the purpose of which is to do four things:
add and store the string GCD(p,q)=m to the array 'aR'; p/q/m are variable stand-ins for the values of the input text areas #IA, #IB, and #CGCD (the GCD of #IA and #IB);
display the array 'aR' in a text-area #PGCD each time the reset button is clicked; this is why I used an array;
clear the two input text areas #IA and #IB;
clear the one output text area;
As it stands, all four objectives are completed successfully, with one exception: for the second objective, only the most recent GCD calculation is outputted; none of the previous calculations output.
I cannot get the array to list the different saved calculations within it. I think (?) the new calculations are being added to the array, but I am not sure.
I've tried a 'for' statement, and an 'if' statement, neither of which worked. I don't know whether I coded it wrong, or if it wasn't the right solution for my issue.
I tried to search the forums (here) for a solution, but was unable to find one.
Thank you.
If I'm understanding what you are describing, I believe your problem is that you are attempting to use += to add elements to an array. You should use
aR.push("GCD(" + p + "," + q + ")=" + m);
The += operator is used for addition of a value to itself as well as string concatenation.
Edit: per comments below, the main issue was declaration of aR as a local variable. It needs to be either global or declared within the same scope.
I am writing a small game in javascript. When the user presses a button, text is returned. I am getting the feeling that there is an easier way than writing:
document.getElementById("logBox").innerHTML = "<p> X event is happening <p>" + document.getElementById('logBox').innerHTML;
So I am trying to write a function I can use like this:
function LOG(input){
document.getElementById("logBox").innerHTML = "<p> input <p>" + document.getElementById('logBox').innerHTML;
}
But even using the special characters sign like \ I have not been able to make it work. I have been searching for a solution but cannot seem to find one. Any suggestions? Thanks
function LOG(input){
// get the #logBox element, then keep it in a variable
// until the end of the function
var logBox = document.getElementById("logBox");
// This will never work -- unless you literally want to add a paragraph
// that says "input" each time you call this function.
// logBox.innerHTML = "<p> input </p>" ...
// Try this
logBox.innerHTML = "<p>" + input + "</p>" + logBox.innerHTML;
}
I'm minifying Javascript in production with jsMin.php https://github.com/rgrove/jsmin-php/
Here is the unminified JS code:
function arc(r, p, a) {
return "A" + r + "," + r + " 0 " + +(a > Math.PI) + ",1 " + p;
}
and the minified code:
function arc(r,p,a){return"A"+r+","+r+" 0 "++(a>Math.PI)+",1 "+p;}
When minified, the code throws an 'unexpected identifier' error. If I take the + sign before (a > Math.PI) away, it works okay.
I guess my question has two parts - why is this an error when it's all on one line, and am I changing the way it works by removing the second + sign? It seems to work okay without it, but I didn't write the code so I'm not entirely sure what it's doing.
You shouldn't be getting an "unexpected identifier" error from the minified code you've presented. If you are, it's a bug in the JavaScript engine you're using it with. That was true of the code you posted originally, which was:
function arc(r,p,a){return"A"+r+","+r+" 0 "+ +(a>Math.PI)+",1 "+p;}
// You used to have a space here -----------^
But with the updated code you've posted:
function arc(r,p,a){return"A"+r+","+r+" 0 "++(a>Math.PI)+",1 "+p;}
// No space here anymore -------------------^
...it's a problem, because the ++ is an increment operator (either the prefix [++a] or postfix [a++]). And that would need an identifier (the thing to increment). The ++ just isn't valid in that position (the exact error you get is likely to vary by JavaScript engine).
You can defend the code against the minifier doing this by changing it slightly:
function arc(r, p, a) {
return "A" + r + "," + r + " 0 " + (+(a > Math.PI)) + ",1 " + p;
}
The parens prevent the + and the other + from getting combined into ++. They also make the intent a bit clearer, IMHO.
Re the second part of your question, no, you can't remove that +, it will change how the function works. In particular, a > Math.PI will be true or false, and the + is there to make it a number (1 for true, 0 for false) before it's concatenated to the string. If you remove it, you'll see true or false in the string instead of 1 or 0.
I guess the problem isn't really there, but just before, even if it looks like it's here because the invalid token is function. Try to add ; :
;function arc(r,p,a){return"A"+r+","+r+" 0 "+ +(a>Math.PI)+",1 "+p;};
I'm a little surprised that the minifier did let the ; before the }, though. It's useless.
I'm creating a GreaseMonkey script to improve the user interface of the 10k tools Stack Overflow uses. I have encountered an unreproducible and frankly bizarre problem that has confounded me and the others in the JavaScript room on SO Chat. We have yet to find the cause after several lengthy debugging sessions.
The problematic script can be found here. Source - Install
The problem occurs at line 85, the line after the 'vodoo' comment:
return (t + ' (' + +(+f.offensive + +f.spam) + ')');
It might look a little weird, but the + in front of the two variables and the inner bracket is for type coercion, the inner middle + is for addition, and the other ones are for concatenation.
Nothing special, but observant reader might note that type coercion on the inner bracket is unnecessary, since both are already type coerced to numbers, and type coercing result is useless when they get concatenated into a string anyway. Not so! Removing the + breaks the script, causing f.offensive and f.spam to be concatenated instead of added together.
Adding further console.log only makes things more confusing:
console.log(f.offensive + f.spam); // 50
console.log('' + (+f.offensive + +f.spam)); // 5, but returning this yields 50 somehow
console.log('' + (+f.offensive + +f.spam) + ''); // 50
Source: https://chat.stackoverflow.com/transcript/message/203261#203261
The problem is that this is unreproducible - running scripts like
console.log('a' + (+'3' + +'1') + 'b');
in the Firebug console yields the correct result, as does
(function(){
return 'a' + (+'3' + +'1') + 'b';
})();
Even pulling out large chunks of the code and running them in the console does not reproduce this bug:
$('.post-menu a[id^=flag-post-]').each(function(){
var f = {offensive: '4', spam: '1'};
if(f){
$(this).text(function(i, t){
// Vodoo - please do not remove the '+' in front of the inner bracket
return (t + ' (' + +(+f.offensive + +f.spam) + ')');
});
}
});
Tim Stone in the chatroom has reproduction instruction for those who are below 10k.
This bug only appears in Firefox - Chrome does not appear to exhibit this problem, leading me to believe that this may be a problem with either Firefox's JavaScript engine, or the Greasemonkey add-on. Am I right?
I can be found in the JavaScript room if you want more detail and/or want to discuss this.
As part of the userscript's process, a <script> tag is injected into the page with the code retrieved by calling toString() on the function you've defined. Usually this would be fine, but it appears that there's a bug in the javascript engine used by Firefox 3.6.13 that relocates the parentheses in the expression, causing it to be evaluated in a very different way when the toString()-ified function is processed.
To illustrate this problem, we can run the following code in Firebug:
function f() { var a = '', b = '1', c = '2'; return a + '(' + (+b + +c) + ')'; };
f.toString();
This gives us this output:
function f() {
var a = "", b = "1", c = "2";
return a + ("(" + + b + + c + ")");
}
You'll note that the return expression has been modified. The parentheses have been relocated beyond the strings that were previously outside of them, causing the variables b and c to be coerced to strings and concatenated. This gives an unexpected result, since the expected addition never takes place. Unfortunately, this behaviour is present even when using Number() or parseInt() to coerce b and c.
There are several small modifications which change this, but the clearest is simply to save the result of the addition to a variable beforehand:
$(this).text(function(i, t){
var c = +f.offensive + +f.spam;
return (t + ' (' + c + ')');
});
Thankfully, this problem seems to not occur in the Firefox 4 beta, so hopefully this issue has been resolved going forward. Also, Matthew Flaschen has graciously gone ahead and filed a bug report (marked duplicate of 559438) so that the developers are made aware of this issue in either case.