I want to know what is happening behind the scenes with the + operator.
console.log(1 + 2);
console.log(1 + "s");
In the above two example, addition and concatenation are both happening using a single (+) operator.
As I've found, JavaScript doesn't support operator overloading. So how is JavaScript handling it?
// Number + Number -> addition
1 + 2 // 3
// Boolean + Number -> addition
true + 1 // 2
// Boolean + Boolean -> addition
false + false // 0
// Number + String -> concatenation
5 + 'foo' // "5foo"
// String + Boolean -> concatenation
'foo' + false // "foofalse"
// String + String -> concatenation
'foo' + 'bar' // "foobar"
All examples from MDN
The reason is that variables will be cast to whichever type is appropriate.
When you add 1 + "s", 1 is converted to string, so you have "1" + "s". Since + is a concatenation operator with strings the results will be "1s".
There are weirder examples:
var result = 'b' + 'a' + + 'a' + 'a';
will give:
>> baNaNa
Adding arrays can give unexpected results too:
var result = [1, 2, 3] + [4, 5, 6];
console.log(result);
will give
>> '1,2,34,5,6'
There are some more really interesting examples here:
https://github.com/denysdovhan/wtfjs
Javascript is a language full of quirks, it's well worth understanding at least some of them.
Related
Had a bug caused by this and while the fix is easy, (switch to r.includes()) I don't know why this occurred.
import _ from 'lodash';
console.log("TEST");
var r = _.range(1, 10 + 1);
console.log("_.range(1, 11): " + r);
console.log("Array.isArray(r): " + Array.isArray(r));
console.log("_.has(r, 2): " + _.has(r, 2));
console.log("_.has(r, 20): " + _.has(r, 20));
console.log("_.has(r, 10): " + _.has(r, 10)); // ???
console.log("x.includes(10): " + r.includes(10));
Results in
TEST
_.range(1, 11): 1,2,3,4,5,6,7,8,9,10
Array.isArray(r): true
_.has(r, 2): true
_.has(r, 20): false
_.has(r, 10): false
x.includes(10): true
Why does _.has(r, 10) result in false? Is it a bug or am I just not understanding something?
While the values in the array are set by lodash as 1-10 (by your _.range(1, 10 + 1)), the keys of the underlying JS array remain 0 based.
You are effectively creating: [1,2,3,4,5,6,7,8,9,10]
_.has checks wether a path exists and in this case is looking for r[10], but in the array above the last valid index is r[9] (since it's 0 based) So it returns false.
(Similarly, if you do _.has(r, 0) you will see true)
has is used to check for a direct property of an object.
What you want to check is: If this array contains a value.
And this is answered by the Array method: includes.
Reference
has from Lodash Document
I was reading the re-introduction to JavaScript on MDN and in the section Numbers it said that you can convert a string to a number simply by adding a plus operator in front of it.
For example:
+"42" which would yield the number output of 42.
But further along in the section about Operators it says that by adding a string "something" to any number you can convert that number to a string. They also provide the following example which confused me:
"3" + 4 + 5 would presumably yield a string of 345 in the output, because numbers 4 and 5 would also be converted to strings.
However, wouldn't 3 + 4 + "5" yield a number of 12 instead of a string 75 as was stated in their example?
In this second example in the section about operators wouldn't the + operator which is standing in front of a string "5" convert that string into number 5 and then add everything up to equal 12?
What you are talking about is a unary plus. It is different than the plus that is used with string concatenation or addition.
If you want to use a unary plus to convert and have it added to the previous value, you need to double up on it.
> 3 + 4 + "5"
"75"
> 3 + 4 + +"5"
12
Edit:
You need to learn about order of operations:
+ and - have the same precedence and are associated to the left:
> 4 - 3 + 5
(4 - 3) + 5
1 + 5
6
+ associating to the left again:
> 3 + 4 + "5"
(3 + 4) + "5"
7 + "5"
75
unary operators normally have stronger precedence than binary operators:
> 3 + 4 + +"5"
(3 + 4) + (+"5")
7 + (+"5")
7 + 5
12
You could also use parseInt() or parseFloat(), like this:
> 1 + 2 + "3"
"33"
> 1 + 2 + parseInt(3)
6
I think that's alot cleaner than using +"3", but that is just my opinion.
The answer can be found in Ecma262.pdf section 11.6.1:
If Type(lprim) is String or Type(rprim) is String, then a. Return the
String that is the result of concatenating ToString( lprim) followed
by ToString(rprim).
So that will resolve all operations according to precedence, so that as soon the string is found any number, the number is converted to string.
4 + 3 + "5"
"75"
4 + 3 + "5" + 3
"753"
To read the whole standard, go here.
When you look at Step 7 and "Note 2" at The Addition operator ( + ) (§11.6.1) in the ES5 specs,
it says
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)
NOTE 2 Step 7 differs from step 3 of the comparison algorithm for the relational operators (11.8.5), by using the logical-or operation instead of the logical-and operation.
Meaning if either 7 (3+4) or "5" (|| not &&) is typeof "string" toString() is applied to both operands.
So the addition is actually applied to
"7" and "5" -> "7" + "5" //"75"
A smple + operator in javascript is used for concatenation and not to add.
A bracket and a + operator before the string format integer variable will do the job every time.
This always works fine.
1 + (+"2") = 3
Because placing + before string converts the string variable into number.
fiddle here: http://jsfiddle.net/xuVur/2/
In the example of 3 + 4 + "5" - the Javascript parser will do (3+4)+"5", as the 3+4 is first - so it will add 3 + 4 because they are numbers, then concatenate the string "5".
When you add a number and a string in Javascript the result is always a string.
Check the experiment here - http://jsfiddle.net/xuVur/1/
var a = "3" + 4 + 5;
var b = 3 + 4 + "5";
$("#result1").html(a); // prints 345
$("#result2").html(b); //prints 75
It is confusing, but binary + seems to be a rare case of a number being coerced to a string. In most cases it would be the other way round (so it's very easy to think that you don't need to be too fussy about the type)
4+"3" = "43"
4-"3" = 1
Why does an empty array plus false return the string "false"?
> [] + false
> "false"
An empty array is false, right?
Then false + false = false? No?
Short answer: because the spec says so.
Longer answer: When the left operand of the + operator is not a string or a number, the operand will be converted to either one of those depending on their "preferred" primitive type (defined in the spec). The array's "preferred" type is a string and [].toString() is an empty string.
Then, still according to the spec, because the left operand is a string (following the previous conversion), the right operand will be converted to a string and the result of the + operation will be the concatenation of both strings.
In other words, [] + false is equivalent to [].toString() + false.toString() (or "" + "false") and results in the string "false".
Other interesting results as a consequence of this:
[1,2,3] + false // "1,2,3false"
[1,[2]] + false // "1,2false"
[] + {} // "[object Object]"
The '+' operator casts to string or number (whatever is possible).
It doesn't cast to Boolean, check it out for yourself:
const x = [] + false;
const y = false + false;
console.log(typeof(x)); // string
console.log(typeof(y)); // number
The general rule for addition in JavaScript is simple: You can only add numbers and strings, all other values will be converted to either one of those types.
Source: https://2ality.com/2012/11/coercing-objects.html
First the + operator must make sure that it operates on primitives (either numbers or strings). If an operand isn't a primitive it must first convert it.
Here are the rules:
If the operand is a primitive then stop.
Otherwise call its .valueOf() method. If the return value is a primitive then stop.
Otherwise call its .toString() method.
In [] + false, [] isn't a primitive. Let's convert it:
([]).valueOf(); //=> [] (not a primitive)
([]).toString(); //=> "" (primitive)
We now have "" + false to solve.
If any operand is a string, then + returns the concatenation of both operands. Meaning that false must be converted to a string:
(false).toString(); //=> "false"
The final operation becomes "" + "false" which returns "false".
What does false + false return?
Both operands are primitives and both aren't strings. So they must both be converted to numbers.
Number(false); //=> 0
+false; //=> 0
Therefore false + false becomes 0 + 0 which returns 0.
How to make [] + false returns 42?
Simple:
Force [] to return 42
42 + false will cause false to be coerced into a number: 0
42 + 0 returns 42
Example:
var empty_arr = [];
empty_arr.valueOf = () => 42;
console.log(empty_arr + false);
Or: (but that's nasty)
Array.prototype.valueOf = () => 42;
console.log([] + false);
Basically it's because JS is trying to concat an array and then adds the string. Take a look on this:
[1] + true // "1true"
[2] + 5 // "25"
[2, 3, 4] + 5 // "2,3,45"
Similar to:
"".concat([3, 2, 1]); // "3,2,1"
More info: Why is [1,2] + [3,4] = "1,23,4" in JavaScript?
var fir=prompt("Enter first Number");
var sec=prompt("Enter second number");
var sum=Number(fir)+Number(sec);
alert("The sum is " + sum);
alert("The difference is " + fir-sec);
alert("The product is " + fir*sec);
alert("The division is " + fir/sec);
Now: suppose fir=2 and sec=1.
The output is:
3
NaN
2
2
Why is the difference NaN instead of 1?
* and / have higher operator precedence than + and -, just like with PEMDAS order of operations in standard math. Specifically, + and - have precedence 13, whereas * and / have precedence 14.
When an expression has + and -s only, they're evaluated in left-to-right order. So, your code is equivalent to:
alert(("The Difference is " + fir) - sec);
alert("The product is " + (fir*sec));
alert("The division is " + (fir/sec));
In the second and third alert, fir and sec get combined into a single numeric expression before being concatenated with the prior string.
In the first alert, "The Difference is " + fir get put together first, resulting in another string (a string + a number results in another string). So then you have
alert((someString) - sec);
But someString - sec doesn't make sense - you can't subtract something from a string, so the expression resolves to NaN.
You can do one thing
var fir=prompt("ENter 1st Number");
var sec=prompt("Enter second number");
var sum=Number(fir)+Number(sec);
var sub=Number(fir)-Number(sec);
alert("The Sum is " + sum);
alert("The Difference is " + sub);
alert("The product is " + fir*sec);
alert("The division is " + fir/sec);
Usually, the plus operator + sums numbers.
But, if the binary + is applied to strings, it merges (concatenates) them:
let s = "my" + "string";
alert(s); // mystring
Note that if one of the operands is a string, the other one is converted to a string too.
For example:
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
See, it doesn’t matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, the other one is converted into a string as well.
However, note that operations run from left to right. If there are two numbers followed by a string, the numbers will be added before being converted to a string:
alert(2 + 2 + '1' ); // "41" and not "221"
String concatenation and conversion is a special feature of the binary plus +. Other arithmetic operators work only with numbers and always convert their operands to numbers.
For instance, subtraction and division:
alert( 2 - '1' ); // 1
alert( '6' / '2' ); // 3
reference https://javascript.info/operators
Because you're concatenating a string ("The difference is") with a number, obtaining a string, and then subtracting a number from it. Use parentheses
alert("The Difference is " + (fir-sec));
The problem you face is due to dynamic type conversion. In your second alert JS engine 1st concatenates "The Difference is " and fir and then subtracts sec. You have to add braces:
alert("The Difference is " + (fir-sec))
In all other cases it is ok because * and / operators have higher priority than + operator
Remeber Math's BODMAS theory,
in case of multiplication and division it works and giving you result.
But for substraction, it first does addition.
And finally:
String - Number = NaN
This question already has answers here:
Why does JavaScript handle the plus and minus operators between strings and numbers differently?
(7 answers)
Closed 6 years ago.
The following code gives weird results:
console.log("" + 1 + 10 + 2 - 5 + "8");
I've tried inputting various different values to work it out but I cannot understand what's going on under the hood.
"" + 1 === "1"
"1" + 10 === "110"
"110" + 2 === "1102"
"1102" - 5 === 1097
1097 + "8" === "10978"
In JavaScript, the + operator is used for both numeric addition and string concatenation. When you "add" a number to a string the interpreter converts your number to a string and concatenates both together.
When you use the - operator, however, the string is converted back into a number so that numeric subtraction may occur.
When you then "add" a string "8", string concatenation occurs again. The number 1097 is converted into the string "1097", and then joined with "8".
string + number = concatenated string
number + number = the sum of both numbers
string - number = the difference between (coerced string) and the number
explanation:
If one or both operands is string, then the plus is considered as string concatenation operator rather than adding numbers.
the minus operator always try to convert both operands to numbers.
so:
"" + 1 + 10 + 2 = (string) "1102"
"1102" - 5 = (number) 1097
1097 + "8" = (string) "10798"
This is a string not a number--""
This is a string not a number--"1"
This is a string not a number--"1" <+> "10" = "1"+"10" = "110"'
This is a string not a number--"1" <+> "10" <+> "2" = "1"+"10"+"2" = "1102"
This is a number because there's no confusion about a minus operator--1102 - 5 = 1097
This is a string not a number--"1097" <+> "8" = "1097"+"8" = "10978"
SNIPPET
document.getElementById("1").innerHTML = "";
document.getElementById("2").innerHTML = "" + 1;
document.getElementById("3").innerHTML = "" + 1 + 10;
document.getElementById("4").innerHTML = "" + 1 + 10 + 2
document.getElementById("5").innerHTML = "" + 1 + 10 + 2 - 5
document.getElementById("6").innerHTML = "" + 1 + 10 + 2 - 5 + "8";
<ol>
<li id='1'></li>
<li id='2'></li>
<li id='3'></li>
<li id='4'></li>
<li id='5'></li>
<li id='6'></li>
</ol>
This site has some useful info.
JavaScript is very relaxed about the difference between strings and numbers.
...
So if you use + on a string and a number, JavaScript is going to make
the number a string for you. Better still, if you need it you can
treat numbers as strings or strings as numbers.
Conversely, if you apply mathematics to a string, JavaScript tries to
make it a number. If the string cannot be interpreted as a number
(because there are letters in it, for instance), JavaScript gives NaN
(Not a Number).
While + and - may have the same Operator Precedence, they do not have the same implicit conversion rules.
As - always means number subtraction in JavaScript, using - will always implicitly attempt parsing both the left and right side of the expression as integer.
In this case, as the operator precedence is the same, and the evaluation is from left to right, you end up with (""+1+10+2) using +'s implicit tostring conversion for string concatenation, or the string "1102". Next, the - will implicitly attempt to parse the string "1102" into a number, as well as the number 5, which results in 1102-5, or the number 1097. At this point the string "8" is concatenated implicitly using +, and the end result can be seen: the string "10978".
Perhaps an interesting alternative would have been ""+1+10+2-5+8, which would have been 1097+8, or the number 1105.