What does +a + +b mean in JavaScript? - javascript

There was an answer to a nested array problem on stack overflow that involved a return statement +a + +b. (no period) What is this? What does it do? It seems to add, but I'm not sure how it does that. How does it differ from a + b? The code is below, and it works:
var array= [1, 2, [3, 4], [], [5]];
var sum = array.toString().split(",").reduce(function(a, b) { return +a + +b;
});
console.log(sum);

The + before the variable is the unary + operator. You are probably familiar with the unary -, e.g. -x.
Both +x and -x convert x to a number, but -x also changes its sign. This is not the primary purpose of the existance of the unary +, but it is a nice sideeffect.
Therefore, the difference between a + b and +a + +b would be visible from this example:
x = '9'; // '9'
x = +'9'; // 9
x = '9' + '9'; // '99'
x = +'9' + +'9'; // 18

JavaScript is dynamically typed, but has no built-in operators for casting a value to ensure it is the right type for an operation. Consequently, various tricks are used when it's important that a value is treated as a number, or a string, etc.
In this case, the operator being used is the "unary +" which is the natural counterpart of the "unary -" that would be used to write a negative number: just as "-x" means "0 - x", "+x" means "0 + x". On a number, this has no effect, but other values will be converted to a number.
This is important because the "binary +" operator does different things depending on the type of its operands: if a was a string, a + b would mean "append two strings together" rather than "sum two numbers".
Given an imaginary cast_to_number function, the equation could be more readably written as return cast_to_number(a) + cast_to_number(b).

Assuming a or b were of type String, adding a + operator in front of it will coerce it to a number.
This ensures that ’1’ + ‘1’ will be 2 (addition of numbers) and not 11 (concatenation of strings).

javascript has a unary operator + and -, both of them converts the operand to a number type, but the - operator negate the result.
for example:
> -'20'
-20
> +'500' + +'600'
1100

The + unary operator is used for explicit coercion in JavaScript.
Even though some developers look down upon it, saying var num = 3 + +c; is rather ugly especially to people not aware of the coercion at hand, potentially even "error-like" looking piece of code.
The most common practical use of the + unary operator is probably to get a number timestamp of the date
var timestamp = +new Date(); // this works!
Perhaps a good piece of memorablia is the - unary operator, which for some reason our human brain seems much happier to interpret. Basically, if we see var x = -c; we presume the compiler:
Attempts to do a value to number coercion of the variable c
If it can return a number, flip the sign and return the negative number (-)
The + unary operator does the same thing, only without the sign flipping.

Related

Discord.js Can't add two texts which properties are numbers together [duplicate]

I am trying to learn Javascript. Here I am confused with the following code.
http://rendera.heroku.com/usercode/eae2b0f40cf503b36ee346f5c511b0e29fc82f9e
When I put x+y in the function it is going wrong. For example 2+2=22, 5+7=57
But /, *, - are working. Why is + not working? Please help me. Thanks a lot in advance
One or both of the variables is a string instead of a number. This makes the + do string concatenation.
'2' + 2 === '22'; // true
2 + 2 === 4; // true
The other arithmetic operators / * - will perform a toNumber conversion on the string(s).
'3' * '5' === 15; // true
A quick way to convert a string to a number is to use the unary + operator.
+'2' + 2 === 4; // true
...or with your variables:
+x + +y
+ has two uses. One is addition, the other however is string concatenation. If one or both of your variables is a string, then + will concatenate them.
You will need to use parseInt or parseFloat to turn a string into a number.
In Javascript the + operator can either perform addition or concatenation depending on the type of its operands. When numbers are used with + it uses addition, but when strings are used with + it concatenates (joins the strings) instead
If the numbers that you are trying to add are 10 and 12, if they resulting sum is supposed to be 22, then you should probably do it as
+10 + +12
And the result might be a string like 1012 if one or both of the numbers is a string.
this works every time
((x*1) + (y*1))
Unary plus should work:
var totalVal = (+2) + (+2);
alert(totalVal);
// result 4
The addition operator works the following way:
1) If at least one operand is a string, then another is converted to string and concatenation is performed;
1 + "2" // "12"
"2" + "3" // "23"
"2" + null // "2null", null is converted to "null"
2) In other cases both operands are converted to numbers:
1 + null // 2, null is converted to 0
1 + undefined // NaN, undefined is converted to NaN
Check the post JavaScript's addition operator demystified for more details.

+ operator is concatinating rather adding even after parseFloat method

In following expression
parseFloat((($scope.Product.cost/100) * $scope.Product.profit) + $scope.Product.cost);
+ operator is concatinating the values and i expect it to perform addition.
...even after parseFloat method
The + part of that expression isn't after the parseFloat, it's before the parseFloat.
You probably wanted:
(($scope.Product.cost/100) * $scope.Product.profit) + parseFloat($scope.Product.cost);
Note that cost in the above is implicitly converted to number when you use it in the /100 expression, but you're explicitly converting it with parseFloat elsewhere. Those two things don't do quite the same thing.
I'd probably prefer to convert, then calculate:
var cost = parseFloat($scope.Product.cost); // or +$scope.Product.cost
var profit = parseFloat($scope.Product.profit); // or +$scope.Product.profit
var result = ((cost/100) * profit) + cost;
See this answer for a rundown of the differences between implicit string-to-number conversion vs. parseFloat (and others).
Side note: You don't need some of the parens you're using, the last line of the convert-then-calculate above could be:
var result = (cost/100) * profit + cost;
...because * has higher precedence than +. But the extra () are harmless.
Convert each of the variables in your expression to number by applying the + unitary operator on each of them:
+$scope.Product.cost/100 * +$scope.Product.profit + +$scope.Product.cost;
As noted in comments, the coercion to float is implied for the first part of the expression by the / and * operators, but not so for the + operator, which will coerce the first numerical result to string unless the second argument is first converted to number as well.
So the first two + unitary operators are not really necessary.

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);

Autoconversion in javascript: Isn't it supposed to convert a string to a number when done like stringvar = 1+stringvar?

(Firefox32, Win 7)
When using the scratchpad:
var a = "2";
a = 1 - 1 + a;
console.log(a, typeof a);
a = 1 + a - 1;
console.log(a, typeof a);
leads in the console to:
"02" "string"
101 "number"
Am I doing something wrong?
I'm sure I have converted strings to numbers that way very often, and it worked. (Though I like to use the explicit converting functions much more, but as it worked so flawlessly for so long, ... :/ )
And why is the third line a number? But not the second? And why is it 101?
Isn't it supposed to convert a string to a number when done like stringvar = 1+stringvar?
Nope. :-) If either operand is a string, it's string concatenation, not addition. This is defined by §11.6.1 of the spec in Step 7:
Let lref be the result of evaluating AdditiveExpression.
Let lval be GetValue(lref).
Let rref be the result of evaluating MultiplicativeExpression.
Let rval be GetValue(rref).
Let lprim be ToPrimitive(lval).
Let rprim be ToPrimitive(rval).
If Type(lprim) is String or Type(rprim) is String, then
Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim). See the Note below 11.6.3.
(My emphasis on "or")
Re your third example, 1 + a - 1 where a is "02":
1 + "02" - 1
The addition (binary +) and subtraction (binary -) operators have the same precedence and both are left-to-right associative, so that's performed like this:
(1 + "02") - 1 => "102" - 1 => 101
The + is string concatenation, but since the subtraction operator - always works with numbers, it coerces the "102" to 102 before subtracting 1 from it to get 101.
This is how string concatenation works.
// Number + String -> concatenation
5 + "foo" // "5foo"
– MDN's Addition Operator usage examples
You can get around this by using the Unary Plus operator (+) to avoid having to call parseInt:
a = 1 + +a;
Unary plus (+)
The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.

Preventing concatenation

I've been writing JavaScript on and off for 13 years, but I sort of rediscovered it in the past few months as a way of writing programs that can be used by anyone visiting a web page without installing anything. See for example.
The showstopper I've recently discovered is that because JavaScript is loosely typed by design, it keeps concatenating strings when I want it to add numbers. And it's unpredictable. One routine worked fine for several days then when I fed different data into it the problem hit and I ended up with an impossibly big number.
Sometimes I've had luck preventing this by putting ( ) around one term, sometimes I've had to resort to parseInt() or parseFloat() on one term. It reminds me a little of trying to force a float result in C by putting a .00 on one (constant) term. I just had it happen when trying to += something from an array that I was already loading by doing parseFloat() on everything.
Does this only happen in addition? If I use parseInt() or parseFloat() on at least one of the terms each time I add, will that prevent it? I'm using Firefox 6 under Linux to write with, but portability across browsers is also a concern.
The specification says about the addition operator:
If Type(lprim) is String or Type(rprim) is String, then
Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
Which means that if at least one operator is a string, string concatenation will take place.
If I use parseInt() or parseFloat() on at least one of the terms each time I add, will that prevent it?
No, all operands have to be numbers.
You can easily convert any numerical string into a number using the unary plus operator (it won't change the value if you are already dealing with a number):
var c = +a + +b;
I normally do this:
var x = 2;
var t = "12";
var q = t+x; // q == "122"
var w = t*1+x; // *1 forces conversion to number w == 14
If t isn't a number then you'll get NaN.
If you multiply by 1 variables you don't know what type they are. They will be converted to a number. I find this method better than doing int and float casts, because *1 works with every kind of numbers.
The problem you are having is that the functions which fetch values from the DOM normally return strings. And even if it is a number it will be represented as a string when you fetch it.
You can use + operator to convert a string to number.
var x = '111'
+x === 111
Rest assured it is very predictable, you just need to be familiar with the operators and the data types of your input.
In short, evaluation is left-to-right, and concatenation will occur whenever in the presence of a string, no matter what side of the operation.
So for example:
9 + 9 // 18
9 + '9' // '99'
'9' + 9 // '99'
+ '9' + 9 // 18 - unary plus
- '9' + 9 // 0 - unary minus
Some ternary expressions:
9 + '9' + 9 // '999'
9 + 9 + '9' // '189'

Categories

Resources