Confusing JavaScript statement about string Concatenation - javascript

I was developing a node.js site and I made a copy and paste error that resulted in the following line (simplified for this question):
var x = "hi" + + "mom"
It doesn't crash and x = NaN. Now that i have fixed this bug, I am curious what is going on here, since if I remove the space between the + signs I get an error (SyntaxError: invalid increment operand)
My Question is : Can some explain to me what is going on in the statement and how nothing (a space between the + signs) changes this from an error to a NaN?
PS. I am not sure if this should go here or programers.stackoverflow.com. Let me know if I posted on the wrong site.

It's being interpreted like this:
var x = "hi" + (+"mom")
The prefix + tries to coerce the string to a number. Number('mom') is NaN, so +'mom' is also NaN.

Related

How to get an 8 decimal output?

I am trying to get an 8 decimal output from the following function.
The following function multiplies an input by 2 and then updates this input with the wagerUpdate variable. I would like this outputted number to have 8 decimal places.
For example: if input number is 0.00000001 (this code is for a bitcoin website), then I would like output number to be 0.00000002. For some reason the code below is not working properly as the output number is in the format of 2e-8 without the .toFixed(8) code. Please help if you are able to. Thank you so much.
<script>
function MultiplyWagerFunction() {
var wager = document.getElementById("wagerInputBox").value;
var wagerUpdate = wager*2;
document.getElementById("wagerInputBox").value = +wagerUpdate.toFixed(8);
}
</script>
If you remove the + before wagerUpdate.toFixed(8) it should work fine. wagerUpdate has already be converted to a number when you multiplied it by 2 so there should be no need for the unary +
var a = "0.00000001";
var b = a*2;
console.log(b.toFixed(8));
console.log(+b.toFixed(8));
^ see the difference.
The reason it doesn't work is because what you are doing is equivalent to:
+(b.toFixed(8))
because of the precedence of the operators (member access . is higher than unary +). You are converting b to a string with .toFixed and then converting it back into a number with + and then converting it back into a string again! (this time with the default toString behavior for numbers giving you exponential notation)
Just remove + from +wagerUpdate.toFixed(8); and you would be good.
Instead of:
document.getElementById("wagerInputBox").value = +wagerUpdate.toFixed(8);
try:
document.getElementById("wagerInputBox").innerHTML = +wagerUpdate.toFixed(8);
Why I say so is may be when you set value, browser tries to convert to best possible outcome. But, inner HTML should take the string equivalent!

java script: 3 + 0 = 30 [duplicate]

This question already has answers here:
Javascript (+) sign concatenates instead of giving sum of variables
(14 answers)
Closed 6 years ago.
JavaScript:
console.log('adding' + addThis + '+' + p1 +'=' + (addThis + p1));
Console in browser returns: adding3+0=30
Im debugging a loop that interpolates two numbers. It works fine until addThis (the amount that needs to be added to the original number) is exactly 3 and p1 (the original value) is 0.
Every time the difference(addThis) has no decimals a wrong calculation happens.
So same problem at:
adding6+0=60 ...or at..
adding9+0=90
...all cases in between work fine (e.g. console returns: adding3.5999999999999996+0=3.59999999999999960)
Dose it 'forget' the point?
Dose it treat those values as strings?
I can't share the whole code but the problem has to be in this simple calculation right?
Thanks a lot for your thoughts and knowledge! ;)
3+0=30. It seems like it must be the string (at least anyone variable is string). You can re-visit the lines where those variable values are initialized/changed. Else you can use like the below:
addThis=Number(addThis); p1=Number(p1);
console.log('adding' + addThis + '+' + p1 +'=' + (addThis + p1));
If you want to convert the strings to integers you can use the parseInt function:
addThis = '3'
p1 = '0'
console.log('adding' + addThis + '+' + p1 +'=' + (parseInt(addThis) + parseInt(p1)))

What does JavaScript interpret `+ +i` as?

An interesting thing I've never seen before was posted in another question. They had something like:
var i = + +1;
They thought the extra + converted it to a string, but they were simply adding to a string which is what caused it to convert.
This, however, lead me to the question: what is going on here?
I would have actually expected that to be a compiler error, but JavaScript (at least in Chrome) is just fine with it... it just basically does nothing.
I created a little JSFiddle to demonstrate: Demo
var i = 5;
var j = + +i;
document.body.innerHTML = i === j ? 'Same' : 'Different';
Anyone know what's actually occurring and what JavaScript is doing with this process?
I thought maybe it would treat it like ++i, but i doesn't increment, and you can even do it with a value (e.g., + +5), which you can't do with ++ (e.g., ++5 is a reference error).
Spacing also doesn't affect it (e.g., + + 1 and + +1 are the same).
My best guess is it's essentially treating them as positive/negative signs and putting them together. It looks like 1 == - -1 and -1 == + -1, but that is just so weird.
Is this just a quirky behavior, or is it documented in a standard somewhere?
Putting your the statement through the AST Explorer, we can see that what we get here is two nested Unary Expressions, with the unary + operator.
It's a unary expression consisting of + and +i, and +i is itself a unary expression consisting of + and i.
The unary expression with the unary + operator, will convert the expression portion into a number. So you're essentially converting i to a number, then converting the result of that to a number, again (which is a no-op).
For the sake of completion, it works on as many levels as you add:
var i = 5;
console.log(+ + + + + +i); // 5
console.log(i); // still 5
It's in the specification.
Digging through, we can see from §14.6.2.2 that the increment and decrement operators are listed before (and should be preferred) over the unary operators. So precedence alone won't explain this.
Looking up the the punctuation table in §11.7, we can see that every single instance of ++ (the operator) in the spec shows the two together, without whitespace. That's not conclusive, until you check...
The whitespace rules in §11.2, specifically:
White space code points may occur within a StringLiteral, a RegularExpressionLiteral, a Template, or a TemplateSubstitutionTail where they are considered significant code points forming part of a literal value. They may also occur within a Comment, but cannot appear within any other kind of token.
JS does not allow arbitrary whitespace mid-operator.
The JS syntax in both PegJS and Esprima corroborate this, matching on the literal two-character string ++.
For me it's very clear;
var a = +3;
var b = +a; // same as a, could be -a, for instance
var c = + +a; // same as above, same as +(+a)
If you do ++variable the javascript interpreter sees it as the increment operator.
If you do + +variable the javascript interpreter sees it as Unary plus, coercing the value to a number, twice.
So
var a = 1;
var b = +a;
var c = +b;
console.log(c);// still 1
is the same as
var c = + +1;
So the simple answer is that two plus signs can not be separated by a space to be interpreted as incrementation, the space makes it so the interpreter sees two seperate spaces, which is what it really is
The + operators converts into a number, two + operators with a space in between does nothing additional.
Even though it might look very similar, + + and ++ are not at all the same thing for an AST interpreter. The same applies to token separation: varfoo is not the same as var foo.
In the expression + + +i, each + is considered as distinct unary operator, which simply convert your variable to a number. For the incrementation operation, which is ++, no spaces are allowed, neither between the + and the variable token. In the example below, the last line is not valid:
var x = "4";
console.log(+ + +x);
console.log(+ + ++x);
console.log(+ ++ +x);

javascript bigger than if statement not working correctly

I am no expert in javascript, so hope someone can help me out.
I have the following code, but for some reason it always thinks the statement is true
delvNum=document.getElementById("deliveryNum").value;
delvQTY=document.getElementById("delvQTY"+id).value;
orderQTY=document.getElementById("orderQTY"+id).value;
if (delvQTY>orderQTY)
{
alert("Can't deliver more than " + orderQTY + ", you are trying to deliver " + delvQTY + ". Please fix!");
document.getElementById("delvQTY"+id).focus();
return;
}
The error message does show the quantity of each var, and is correctly being passed through.
You are comparing strings and not numbers.
Use parseInt or parseFloat
if (parseFloat(delvQTY)>parseFloat(orderQTY))
or
if (parseInt(delvQTY,10)>parseInt(orderQTY,10))
You're doing a string comparison, not number comparison and, for example, "9">"1111" is true.
You need to parse your values :
if (parseFloat(delvQTY)>parseFloat(orderQTY))
See parseFloat.
You need to make sure delvQTY and orderQTY are Number before you can do > comparison.
var delvValue = parseInt(delvQTY, 10); for converting to integers.
Or for floating point numbers: var delvValue = parseFloat(delvQTY);
You're comparing the string values, rather than numerical ones. You should say:
delvNum = parseInt(document.getElementById("deliveryNum").value, 10);
(assume you are dealing with integers, else use parseFloat).
Note the 10 to say you're dealing with base 10 - without it, if someone types a leading zero then you'll get baffling results.

What is the JSLint approved way to convert a number to a string?

I've always converted numbers to strings by adding an empty string to them:
var string = 1 + '';
However, JSLint complains of this method with Expected 'String' and instead saw ''''., and it does look a little ugly.
Is there a better way?
I believe that the JSLint approved way is to call .toString() on the number:
var stringified = 1..toString();
// Note the use of the double .. to ensure the the interpreter knows
// that we are calling the toString method on a number --
// not courting a syntax error.
// You could also theoretically call 1["toString"];
(Sorry, it possibly would've been better to say this as a comment above but I haven't yet earned the right to post comments, so...)
Remember that jslint is not just validating whether your JavaScript will actually run, it is trying to enforce coding style with the aim of helping you produce more readable and maintainable code.
So 1 + '' works, but isn't necessarily the most readable option for everybody while explicit casting options (see the other answers) should be readable for everybody. Of course if nobody else will ever see your code you need only worry about whether you will be able to understand it if you come back to it next month, or next year...
Don't forget that the following two statements don't produce the same result:
var s1 = 1 + 3 + ''; // gives '4'
var s2 = '' + 1 + 3; // gives '13'
I assume 1 + '' is just a simplification for discussion though, or why not just use '1' in the first place?
You can use the .toString() method like so:
var num = 1;
var str = num.toString();
There's also (at least in Chrome): String(1) without new.
var n = 1, s = String(n);
I am going to say "bug" or "mis-feature"
Cole Consider that
var x = "foobar" + 1;
is "approved" jslint. In any case, it is 100% valid Javascript.
Happy coding.
For comment:
This is why I prefer to use the string literal as the first operand as this shows intent -- knowing a language is fundamental to using a language.
The only place the duck-typing is an issues (in this case) is with an expression of the form a + b, where neither is a string literal. In this case a (or b) may evaluate to a string where it was expected to evaluate to a number (this would trigger the string concatenation vs. the expected numeric addition). If any of the operands are a string literal the intent is well-defined/described.
This particular "issue", however, is not present in the posted code; nor would it be eliminated with the use of toString over a string literal.
In my opinion, we should use String(number) instead of number + '' or number.toString(), because
number + '' will trigger the JSLint error
number.toString() will fail in case number is null or undefined, and you will have TypeError: number is undefined / null
Recently, JSLint was in beta. The new version no longer complains about this code:
function convert(x) {
'use strict';
// alert(typeof x);
x = x + "";
// alert(typeof x);
return x;
}
convert(3);

Categories

Resources