Can anyone explain what makes this valid? String in an array multiplied yields the result like the array or string never mattered.
equation
["155"] * 100 = 15500
When a non-numeric value is operated on with something that only makes sense for numeric values - like * or / or % - JS attempts to coerce the non-numeric value into a numeric value. Number(['155']) turns into 155. It's weird, but legal. Usually, if you see code which relies on something like that, it's bad code that deserves refactoring.
This behavior is described in the specification here, ApplyStringOrNumericBinaryOperator:
Let lnum be ? ToNumeric(lval).
Let rnum be ? ToNumeric(rval).
(...do calculations on lnum and rnum)
If the value can't be converted to a sensible number - for example, 'a' - then you'll get NaN as a result, but it doesn't throw an error.
["155"] turns into the number 155 because, when ["155"] is converted to a primitive, it gets joined by ,s: ["155"].join(',') results in the string '155'. This primitive then gets converted into the number 155.
Arrays with more than 1 item can't be converted to numbers, because a comma is not a valid numeric character:
const arr = [1, 2];
console.log(
String(arr),
Number(arr)
);
Related
Here are 2 examples of my code. The first one is:
console.log([4] + 10); //"410"
As far as I know, addition operator can work only with numbers and strings. So, firstly, [4] should be transformed into the number or string. When trying to convert an operand to a primitive data type, either valueOf() or toString() runs. By default, valueOf() returns an array, so this method is ignored. toString() is invoked. It converts the complex data type to a string. That's completely understandable for me, but...
What's going on in the second example?
console.log(10 - [4]); //6
I don't get how valueOf() can transform array into the number if this method by default returns an array. What does occur here?
It goes this way:
10 - [4]
10 - '4' // array to string
10 - 4 // implicit casting of all operands to number with minus operator
6 // result
This question already has answers here:
Why does JavaScript handle the plus and minus operators between strings and numbers differently?
(7 answers)
Closed 5 years ago.
Why does Javascript give an output of 0 when I use the odd operator?
What is the difference between subtraction and addition with a string?
var x = 1;
console.log(x+'1') // Outputs 11
console.log(x-'1') // Outputs 0 -- but why?
So how can I do mathematical calculations?
The + operator has one of two three meanings in javascript. The first is to add numbers, the second is to concatenate strings. When you do 1 + '1' or '1' + 1 the operator will convert one operand that is not a string to a string first, because one other operand is already evaluated to be a string. The - operator on the other hand has just one purpose, which is to subtract the right operand from the left operand. This is a math operation, and so the JS engine will try to convert both operands to numbers, if they are of any other datatype.
I'm not sure though why typecasting to strings appears to have precedence over typecasting to numbers, but it obviously does.
(It seems to me the most likely that this is a pure specification decision rather than the result of other language mechanics.)
If you want to make sure that the + operator acts as an addition operator, you can explicitly cast values to a number first. Although javascript does not technically distinguish between integers and floats, two functions exist to convert other datatypes to their number equivalents: parseInt() and parseFloat() respectively:
const x = 10;
const result = x + parseInt('1'); // 11
const y = 5;
const result2 = y + parseFloat('1.5'); // 6.5
const result3 = y + parseInt('1.5'); // 6
Edit
As jcaron states in the comment below, the + operator has a third meaning in the form of an unary + operator. If + only has a right operand, it will try to convert its value to a number almost equivalent as how parseFloat does it:
+ '1'; // returns 1
+ '1.5'; // returns 1.5
// In the context of the previous example:
const y = 5;
const result2 = y + +'1.5'; // 6.5
Dhe difference with parseFloat is that parseFloat will create a substring of the source string to the point where that substring would become an invalid numeric, whereas unary + will always take the entire string as its input:
parseFloat('1.5no-longer-valid'); // 1.5
+ '1.5no-longer-valid'; // NaN
That is because + is a concatenation operator. So javascript considers it to be a concatenation operator rather than a mathematical operator.But it is not the case with / ,* ,/ etc.
This happens because + its also used to concatenate strings. Then, JS always will find the better way to make the correct typecasts basing on types. In this case, the x+'1' operation, will be identified as string type + string type.
Otherwise, x-'1', will become int type - int type.
If you want to work with specific types, try to use type cast conversions, link here.
EDIT: I will rephrase my question, I type Number < String and it returns true, also works when I do typeof(2) < typeof("2").
Number < String => true
typeof(2) < typeof("2") => true
I'm guessing it is the value of ASCII characters of each letter in Number and String but I am not sure if that is the reason this is returning true, and I want to know why does this happens, what processes or how does the interpreter gets to this result?
First answer:
The charCodeAt() method returns the numeric Unicode value of the character at the given index. Read here
Now if you do not specify any index position then character at 0th index is considered. Now, S ASCII value is 83 and N ASCII value is 78. so, you are getting those number. Check here.
And 78 < 83 => true is obvious.
Try "String".charCodeAt(1) and you will get 116 which is ASCII value of t
Second answer based on OP's edited question:
Frankly speaking your comparison Number < String is "technically" incorrect because Less-than Operator < or any similar operator is for expressions, and Number and String are functions and not expressions. However #Pointy explained on how Number < String worked and gave you results.
More insight on comparison operators
Comparison operators like < works on expressions, read here. Typically, you should have a valid expression or resolved value for RHS and LHS.
Now this is the definition of expression, read more here - "An expression is any valid unit of code that resolves to a value. Conceptually, there are two types of expressions: those that assign a value to a variable and those that simply have a value."
So, (x = 7) < (x = 2) or new Number() < new String() is a "technically" valid/good comparison, even this Object.toString < Number.toString() but really not Object < Function.
Below are rules/features for comparisons, read more here
Two strings are strictly equal when they have the same sequence of characters, same length, and same characters in corresponding positions.
Two numbers are strictly equal when they are numerically equal (have the same number value). NaN is not equal to anything, including NaN. Positive and negative zeros are equal to one another.
Two Boolean operands are strictly equal if both are true or both are false.
Two distinct objects are never equal for either strict or abstract comparisons.
An expression comparing Objects is only true if the operands reference the same Object.
Null and Undefined Types are strictly equal to themselves and abstractly equal to each other.
The result of
Number < String
is not the result of comparing the strings "Number" and "String", or not exactly that. It's the result of comparing the strings returned from Number.toString() and String.toString(). Those strings will (in all the runtimes I know of) have more stuff in them than just the strings "Number" and "String", but those two substrings will be the first place that they're different.
You can see what those actual strings are by typing
Number.toString()
in your browser console.
JavaScript does the following thing:
"String".charCodeAt(); => 83
"S".charCodeAt(); => 83
"String".charCodeAt(0); => 83
The method charCodeAt(a) gets the char code from position a. The default value is 0
If you compare N > S you will get 78 > 83 => true
For the complete String Javascript calculates the sum of all ASCII char codes.
So I can answer your question with yes.
This question already has answers here:
Why does JavaScript handle the plus and minus operators between strings and numbers differently?
(7 answers)
Closed 7 years ago.
I read a book about operators in Javascript, and this confused me.
console.log("5"+1);
This would make "5" as a string. So the result would be 51.
console.log("5"-1);
This result would be 4. I know it converts "5" to 5, but why it isn't shown undefined as "a string minus a number"?
Update: So how about other languages? Are they more restrict?
Sadly, it was expected from JavaScript to ride on Java's success for promotion on its early days and the plus for string concatenation was adopted since Java used it.
So JavaScript tries hard to coerce strings into numbers for you, it really does, its just that the plus was taken for strings so....well...
While Javascript has many strenghts it was made in 10 days and has many hilarious aspects like this one, check this comedy gold
The + is a operator that means SUM when adding numbers and that means CONCATENATE when using Strings.
As the first is a STRING, it will continue concatenating a "5"+toString(1).
As the MINUS (-) operator does not work with String you are getting undefined.
If you want to use MINUS operator, you will need to do :
parseInt("5") -> It will give you 5, the number
parseInt("5")-1 = 4
"5"+1 = 51
parseInt("5")+1 = 6
Hope it will help you
Because when we use '+' it can be used in two different ways:-
1. as mathematical operator.
2. to concatenate strings
but '-' can only be used as mathematical operator.
Hence javascript considers '5' as numerics in case of '-' while '5' as string in case of '+'.
In javascript (+) operator operates the way described below
3+true will return 4 , (+) operator between a number and a boolean or two boolean will convert boolean to number , hence true is converted to 1 hence the result is 4
"2"+true will return "2true" , if one of the operand is string it will convert the other operand (number or boolean) to string and process the concatenation
-"12"+3 will return -9 , (-) operator in front of string will convert the string to number and will make it as -12 and return -9
According to the standard EcmaScript 262. The + and - operators behave differently when strings are involved. The first converts every value to a string. The second converts every value to a number.
From the standard:
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)
This rules implies that if in the expression there is a string value, all values involved in the + operation are converted to a string. In JavaScript when the + operator is used with strings, it concatenates them. This is why console.log("5"+1) returns "51". 1 is converted to a string and then, "5" + "1" are concatenated together.
Nevertheless, the above rule doesn't apply for the - operator. When you are using a - all values are converted to numbers according to the Standard (see below). Therefore, in this case, "5" is converted to 5 and then 1 is subtracted.
From the standard:
5 Let lnum be ToNumber(lval).
6 Let rnum be ToNumber(rval).
Operator definition from the standard EcmaScript 262.
Operator + : http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.1
Operator - : http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.2
Because of the type coercion and how it isn't very consistent in JavaScript, in the second case the "5" is converted to a number 5, and 1 is subtracted from it, giving you 4.
"5" could be coerced to 5 (Integer). That's why you get 4 as output.
However if you try:
console.log("text" - 1);
Text cannot be coerced, and the output is NaN
The subtraction operator (-) subtracts the number to the right of the operator from the number on the left.
When either of the operands are strings, an attempt is made to convert the strings to numbers.
Instead of using "5" if you try console.log("abc" - 1); it will prompt a error as NaN.
Just for the info:
The subtract operator has special rules to deal with the variety of type conversions present in JavaScript:
If the two operands are numbers, perform arithmetic subtract and return the result.
If either number is NaN, the result is NaN.
If Infinity is subtracted from Infinity, the result is NaN.
If –Infinity is subtracted from –Infinity, the result is NaN.
If –Infinity is subtracted from Infinity, the result is Infinity.
If Infinity is subtracted from –Infinity, the result is –Infinity.
If +0 is subtracted from +0, the result is +0.
If –0 is subtracted from +0, the result is –0.
If –0 is subtracted from –0, the result is +0.
If either of the two operands is not a number, the result is NaN.
Trying to get around some JavaScript code I am looking at. I am seeing things like this:
var myVariable = "X";
var result = myVariable * 6;
Coming from a C# background, this is new to me. Could somebody give me a quick primer on what is going on here? I am guessing that result would be equal to that letters position in the alphabet multiplied by 6, would I be correct?
I am guessing that result would be equal to that letters position in the alphabet multiplied by 6, would I be correct?
No. JS is weakly typed, and values are implicitly typecasted to match the operator (a multiplicative one here). In this case, the string "X" would be converted to a number - leading to NaN as it's no valid numberic literal. The result would then be NaN as well.
To get the position in the alphabet, you'd use parseInt function with a non-decimal base (parseInt("X", 36)-10) or the charCodeAt string method ("X".charCodeAt(0)-65).
I think the easiest solution to have a string s repeated n times is:
Array(n+1).join(s)
Reading your question again: To multiply the charcode of the first letter of s by n:
s.charCodeAt(0) * n
To get the character that corresponds to that multiplied charcode:
String.fromCharCode(s.charCodeAt(0) * n)
The result would be NaN because "X" is not a number; multiplying a string with a number will always return NaN.
More information: http://es5.github.com/
The * operator performs multiplication, producing the product of its operands. Multiplication is commutative. Multiplication is not always associative in ECMAScript, because of finite precision.
The result of a floating-point multiplication is governed by the rules of IEEE 754 binary double-precision arithmetic:
If either operand is NaN, the result is NaN.
If you want to get the letter's position in the English alphabet, try this:
myVariable.toUpperCase().charCodeAt(0) - 65;