Почему вычисления происходят именно так?
JS тут не при чем, это особенности вычислений с плавающей запятой, и они описаны в стандарте IEEE 754, и именно так работает большинство процессоров.
Если вы хотите чтобы работало "согласно ожиданиям", то есть варианты:
1. подкорректировать свои ожидания, и работать как все.
2. использовать библиотеки для всяких длинных арифметик и прочих повышенных точностей, платя за эту точность скоростью вычислений.
3. использовать языки, которые будут маскировать проблему, округляя числа втихаря (и рисковать нарваться на неточности уже из-за этих округлений, ага).

https://0.30000000000000004.com/ -- тут подробно, с примерами на разных языках.
Этот же пример разобран тут