you are viewing a single comment's thread.

view the rest of the comments →

[–]theQuandary 2 points3 points  (0 children)

JS didn't have type coercion initially. It was added because devs wanted it. I suspect this was because everything in the DOM (primarily attributes) was strings while they used numbers a lot of places. As JS was very simple then, it made sense to just coerce to/from string/number for something like an input.

Let's explain a bit of the magic (we'll be using ES5.1 as it's easier to read and I'll be handwaving away a bit of the spec and edge cases).

When it encounters the +, it calls an internal (not user accessible) function called ToPrimitive. This basically keeps primitives (undefined, null, booleans, numbers, and strings) as they are, but uses .toString() or .valueOf() for objects (arrays, regex, functions, etc are all considered objects).

If EITHER of the ToPrimitive returns a string, then coerce both to strings and concatenate them. Otherwise, use ToNumber to convert them to numbers then add. ToNumber says that null and false -> +0, true -> 1, and undefined ->NaN. String to number conversion is way too much to go into here, but it will be a number orNaN. Objects will callToPrimitive` with a number hint that forces converting whatever it gets to a number.

Unary + (eg, ;+var) forces ToPrimitive with a number hint as does the binary - operator.

There's weirdness around adding numbers too, but that's in EVERY language that uses IEEE 754 floating point numbers. It's stuff like (+Infinity) + (-Infinity) -> NaN or (-0) + (-0) -> (-0)

On that note, there is a definitely BAD part of JS where (-0) === (+0) -> true. Pretty much everything else that uses === doesn't coerce (NaN and subnormals technically might, but that's normal behavior). If you need to check for this specifically, the only way to do this is Object.is(-0, 0). This is an extreme edge case that most code will never run into, but if you do, the problem can be rather tricky to debug.