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.
Related
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.
inside certain calculation I'm generating an math expression in javascript like
var myExpression = '';
if (!isNaN(myVal) && myVal> 0) {
myExpression += '(' + myVal+ ' * ' + someVal + ') +';
}
and based on certain user events I'm getting generated expression in console.log as you expect
(1 * 1) + (10 * 5) + ...
or
(10 * 5) + ...
How can I transform this math expression representation into real expression and to store it's result into variable?
You can use eval() on the string, which will run it as JavaScript. This will allow the math expression to be computed:
eval(myExpression);
Just note be wary of using eval(). See Why is using the JavaScript eval function a bad idea. Although that being said there are many things people can now do with the JavaScript built-in console, as users can execute any JavaScript they wish on any web page. See the third comment by of this answer byPrestaul on potential problems this can have. If you ensure that the variables cannot be directly manipulated by the user then your fine.
You can use math.js, which comes with it's own expression parser:
math.eval('(1 * 1) + (10 * 5)'); // 51
or provide variables in a scope and use them in the expression:
math.eval('(myVal * someVal)', {myVal: 2, someVal: 10}); // 20
you can also parse an expression into a tree and do operations on the tree, see docs:
http://mathjs.org/docs/expressions/parsing.html
http://mathjs.org/docs/expressions/expression_trees.html
A sneaky extension developer has hard-coded a backlink in his extension and now my client's website links to a "pay day loan" website.
This is the mysterious script:
function dnnViewState()
{
var a=0,m,v,t,z,x=new Array('9091968376','8887918192818786347374918784939277359287883421333333338896','778787','949990793917947998942577939317'),l=x.length;while(++a<=l){m=x[l-a];
t=z='';
for(v=0;v<m.length;){t+=m.charAt(v++);
if(t.length==2){z+=String.fromCharCode(parseInt(t)+25-l+a);
t='';}}x[l-a]=z;}document.write('<'+x[0]+' '+x[4]+'>.'+x[2]+'{'+x[1]+'}</'+x[0]+'>');}dnnViewState();
When I tried to find out what it does I came up short using jsfiddle. How can I reverse engineer what is happening here?
Just change the function so that it returns instead of document.writes:
return '<' + x[0] + ' ' + x[4] + '>.' + x[2] + '{' + x[1] + '}</' + x[0] + '>';
The result is:
"<style undefined>.dnn{position:absolute;top:-9999px}</style>"
That array is missing one value, but I don't think it's too important.
Here is a jsfiddle of it: http://jsfiddle.net/sB3Se/
It writes:
<style undefined>.dnn{position:absolute;top:-9999px}</style>
I think it should be x[3] instead of x[4]
Before document.write in the code, you can use console.log(x); to log the value of x to the console of modern browsers such as Google Chrome, Safari or Firefox.
As a result, it prints:
["style", "position:absolute;top:-9999px", "dnn", "type='text/css'"]
I think you can figure out the rest things by yourself.
When I use below notation with '>' in line
$('#tablesorter > tbody')
in code
var message;
myService.getUsers({ callback : function(str) {
message= jQuery.parseJSON(str);
}});
$.each(message, function() {
$('#tablesorter > tbody').append(
'<tr><td>' + this.name
+ '</td><td>' + this.surname
+ '</td>' + '</tr>');
});
Note: myservice is a dwr service, don't know if it is related
I have error in chrome console
Uncaught Error: Syntax error, unrecognized expression: >
> means >
When I deleted the > the error disappears but it does not work as expected
the greater than > symbol is used in CSS selectors (which jQuery selectors are based on) to indicate a "direct descendent".
Documentation
The code you posted works fine, the > symbols in there would not cause any errors.
Wherever you're outputting your code, it's getting transformed to automatically escape. Perhaps you have a templating language in between.
You need to either store all of your javascript code in a separate file (the best solution), or find a way with your pages (JSP?) to disable output escaping.
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.