1

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

Jeff
  • 607
  • 1
  • 7
  • 17
  • Are you asking why it is doing that, or are you asking why jsfiddle is different? – Taplar Aug 25 '20 at 19:53
  • @CertainPerformance https://jsfiddle.net/rxz4v2cn/ macosx 10.15.3 and chrome 84.0.4147.135 if it matters – Jeff Aug 25 '20 at 20:06
  • @Taplar why it's doing that and what could be causing it. The inner workings of js are always intriguing to me. Even CertainPerformance getting a different result in jsfiddle is interesting – Jeff Aug 25 '20 at 20:07
  • 1
    Umm ... `c = ["100"] * 10000;` ..? – Teemu Aug 25 '20 at 20:08
  • 1
    Thanks, but it looks like you have `const c = ["100"] * 10000;` there - you aren't multiplying the `["166"]` – CertainPerformance Aug 25 '20 at 20:08
  • @CertainPerformance ohhhh well, i screwed up the fiddle, sorry I'm going to edit the question then to what i wondered what it was originally doing. Why a string in an array was being multiplied directly – Jeff Aug 25 '20 at 20:11
  • @CertainPerformance Thanks, that's interesting. If you want the credit post as an answer. I knew about the result of string concatenation stuff like `'44' + 100` and number coercing like `'44' * 100` but never knew why and never thought it would go so far as arrays. Not my code, just something interesting i was curious about. – Jeff Aug 25 '20 at 20:21

1 Answers1

3

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:

  1. Let lnum be ? ToNumeric(lval).
  2. 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)
);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320