Потому что спецификация так говорит . %
(и *
и /
) равны MultiplicativeOperator
с, и когда любой из них используется, обе стороны оператора преобразуются в числа:
Пусть Инум будет?
ToNumeri c (leftValue). Пусть rnum будет?
ToNumeri c (rightValue). Если Type (lnum) отличается от Type (rnum), сгенерировать исключение TypeError. Пусть T будет Type (lnum) ). Если MultiplicativeOperator равен *, вернуть T :: multiply (lnum, rnum). Если MultiplicativeOperator равен /, вернуть T :: div (lnum, rnum).
Остальное,
a. Утверждение: MultiplicativeOperator равен%.
b. Возврат T :: remainder (lnum, rnum).
То же самое происходит, когда -
используется для не чисел - обе стороны приводятся к числам во-первых, после чего выполняется операция. Ошибка не выдается, , если один из ToNumeric
s не возвращает number
, а другой ToNumeric
не возвращает bigint
. BigInts - это единственный тип, который требует ожидаемого приведения типа явного .
Обратите внимание, что в Typescript, который (в основном) является типобезопасной версией Javascript, этот вид вещи действительно приводят к ошибке, а именно:
Правая (или левая) сторона арифметической операции c должна иметь тип 'any' , 'число', 'bigint' или тип перечисления. ts (2363)
Но стандартный Javascript в случае подобных конфликтов типов почти всегда предпочитает попытку выполнить операцию вместо выдачи ошибок. По тем же причинам вы можете сделать
const obj = {};
const someStr = 'foo' + obj;
console.log(someStr);
Что не имеет особого смысла, поскольку obj
является объектом (и в большинстве случаев не может быть очень значимым +
d со строкой), но язык не запрещает это.