[1] + [2] - [3] = 9. Да как так-то?

Вот вам код на JavaScript. Если его исполнить, результат будет 9. Это нелогично для нас, но совершенно понятно, логично и предсказуемо с точки зрения JavaScript. Вот почему.

[1] + [2] - [3] = 9. Да как так-то?

Разбираемся, что лежит в скобках

В JavaScript прямые скобки — это признак того, что перед нами массив. Когда мы объявляем новый массив, то обычно делаем это так:

var arr = [1,2,3,4,5];

Слева у нас переменная, в которую мы отправляем новое значение, а справа — массив, который мы хотим поместить в переменную. Получается, что мы можем просто объявить массив в квадратных скобках, а значит, вот что у нас лежит в этих массивах:

[1] — здесь лежит нечто, похожее на 1

[2] — здесь — похожее на 2

[3] — а здесь — на 3

Здесь всё неопределённо, потому что мы явно не указывали тип данных. По этой причине JavaScript относится к таким данным настороженно и считает их максимально аккуратно.

Теперь сложим первые два массива.

Складываем первые два массива и смотрим на результат

Так как JavaScript выполняет все действия так, как это принято в математике, то сначала он сложит первые два массива между собой.

Проблема здесь в том, что JavaScript в момент вычисления не знает, что конкретно мы имели в виду под числами в этих массивах — числа, строки или что-то ещё. Единственный безопасный способ для JavaScript сложить что-то неизвестное — привести всё к строкам и сложить уже их.

Значит, в момент вычисления [1] + [2] мы по факту получим такое:

"1" + "2", но так как строки при сложении просто соединяются, то в результате будет строка "12":

[1] + [2] - [3] = 9. Да как так-то?

Вычитаем третий массив

JavaScript может складывать друг с другом почти что угодно (через строки и общие типы), но с вычитанием гораздо строже: для вычитания нужны числа. Это значит, что перед тем, как вычитать из одного другое, JavaScript сделает два промежуточных действия:

  • Переведёт строку "12" в число и получит просто 12. Если бы перевод не удался, код бы сразу выдал ошибку приведения типов.
  • Точно так же переведёт [3] в число и получит число 3.

Теперь наши вычисления превратились в простое математическое действие:

12 − 3 = 9

Вот так и выходит, что по отдельности в массивах лежит что-то, похожее на числа, но вместе получаются то строки, то снова числа.

Короче

Когда JavaScript видит плюс, он может интерпретировать его и как «сложение», и как «склеивание» в зависимости от того, какие данные перед ним. Если в данных какая-то каша, JavaScript их скорее склеит, чем сложит.

Минус — это однозначное вычитание и требует только чисел, поэтому JavaScript постарается преобразовать всё в числа.

104104
4 комментария

какая то наркоманская логика. То сначала склеиваются два числа в одну строку, затем эта общая строка становится вдруг снова числом. То то я смотрю, что настоящие "кодеры", с виду похожи на придурковатых зомби.

1
Ответить

Обычные гримасы языка с нестрогой и крайне вольной типизацией.
Если не нравится, что язык молча делает под капотом что-то странное, можно взять Typescript.

Ответить

Ну JavaScript известный наркоманский язык.

Ответить

То есть "+" это склеивание, а "-" это вычитание

Ответить