5

I realized that in javascript all 101/100, "101"/100, 101/"100" and "101"/"100" result in 1.01 (checked on Chrome, FF and IE11). But I cannot find a piece of documentation regarding this behaviour.

Therefore my question is if it is (cross-browser) safe to use this feature, and if it is a good practice to do so (or rather to use parseInt before division if the variable can be a string)?

Arsen
  • 664
  • 1
  • 11
  • 29
  • That's a specification: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures – Praveen Kumar Purushothaman Aug 25 '15 at 11:26
  • 3
    @PraveenKumar: Yes, there is. That isn't it. [This is](http://www.ecma-international.org/ecma-262/6.0/index.html), or more accurately [this PDF](http://www.ecma-international.org/ecma-262/6.0/ECMA-262.pdf). – T.J. Crowder Aug 25 '15 at 11:27
  • Living specification: [evaluation of a MultiplicativeExpression](//tc39.es/ecma262/#sec-multiplicative-operators-runtime-semantics-evaluation), [ApplyStringOrNumericBinaryOperator](//tc39.es/ecma262/#sec-applystringornumericbinaryoperator). – Sebastian Simon Jan 26 '22 at 07:38

3 Answers3

6

When you use / on strings, the strings are implicitly converted to numbers and then division operation is performed.

This may work in all browsers, but it's always good practice to convert to number explicitly using parseInt or parseFloat or other method.

parseInt("101", 10) / 100

Or

parseFloat("101") / 100

ECMAScript Specifications for Division Operator

Tushar
  • 85,780
  • 21
  • 159
  • 179
  • it's a good answer, but the "Applying the / Operator" section in the document You've linked still doesn't regard strings. – Arsen Aug 25 '15 at 12:01
  • 1
    @Arsen: True (it's also the old spec), http://www.ecma-international.org/ecma-262/6.0/index.html#sec-multiplicative-operators-runtime-semantics-evaluation would be the bit that talks about the implicit coercion in the current spec. (But still a good answer, as you said; has my vote.) – T.J. Crowder Aug 25 '15 at 12:10
5

Therefore my question is if it is (cross-browser) safe to use this feature...

It depends on your definition of "safe." With the division operator, yes, it's specified behavior: Each operand is converted (implicitly coerced) to a number, and then numeric division is done.

But beware of generalizing this too far. You'll be okay with /, *, and - but it will bite you on +, because if either operand to + is a string, + does string concatenation, not addition.

Another way that it may or may not be "safe" depending on your point of view is the implicit coercion: It uses the browser's JavaScript engine's rules for converting strings to numbers. Some older browsers went beyond the specification (which they were allowed to in the past) and treated numbers starting with a 0 as octal (base 8) rather than decimal. Naturally, end users who type in, say, "0123" as a number probably mean the number 123, not the number 83 (123 in octal = 83 decimal). JavaScript engines are no longer allowed to do that, but some older ones do.

In general, it's probably best to explicitly coerce or convert those operands. Your choices for doing so:

  • The unary + operator: value = +value will coerce the string to a number using the JavaScript engine's standard rules for that. Any non-digits in the string (other than the e for scientific notation) make the result NaN. Also, +"" is 0, which may not be intuitive.

  • The Number function: value = Number(value). Does the same thing as +.

  • The parseInt function, usually with a radix (number base): value = parseInt(value, 10). The downside here is that parseInt converts any number it finds at the beginning of the string but ignores non-digits later in the string, so parseInt("100asdf", 10) is 100, not NaN. As the name implies, parseInt parses only a whole number.

  • The parseFloat function: value = parseFloat(value). Allows fractional values, and always works in decimal (never octal or hex). Does the same thing parseInt does with garbage at the end of the string, parseFloat("123.34alksdjf") is 123.34.

So, pick your tool to suit your use case. :-)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • `"10" * 1` and `"10"/1` can also be used for type casting, is there any disadvantage of using them for this purpose – Tushar Aug 26 '15 at 10:27
  • 1
    @Tushar: Multiplication and division are expensive, so using `*1` or `/1` is relying on the JavaScript engine to optimize the actual operation out and just do the coercion. I'm not entirely sure it can even do that (what with the vagaries of IEEE-754 math). Of course, 99.999% of the time, performance doesn't matter, and modern systems offload floating point to the chip. But the `+` idiom is very deeply ingrained in JavaScript culture and doesn't have that issue, so... (Another one you see often is `value = value|0`.) – T.J. Crowder Aug 26 '15 at 10:56
0

Type coercion is at play here. Quoting @Barmar's answer from What exactly is Type Coercion in Javascript?

Type coercion means that when the operands of an operator are of different types, one of them will be converted to an "equivalent" value of the other operand's type.

The reason for your observation is valid for other operations too -

1 + "2" will give you "12"
1 - "2" will give you -1 

(because "-" operation on strings is not defined like division")

In the case "101/100" the operation "/" will decide the coercion, since there is no operation defined on strings with that operator "/", but is there for "numbers".

Using it is safe (at least in modern browsers) as long as you are clear how type coercion will play out in your operation.

Community
  • 1
  • 1
amulous
  • 704
  • 2
  • 6
  • 15
  • 1
    "Type coercion means that when the operands of an operator are **different types**" - it doesn't apply to the "101" / "100" = 1.01 case thou. – Arsen Aug 25 '15 at 12:57
  • @Arsen In that case the operation "/" will decide the coercion, since there is no operation defined on strings with that operator "/". – amulous Aug 25 '15 at 13:01