На хабре вышла статья (https://habr.com/ru/companies/timeweb/articles/769844/) под названием "8 углубленных вопросов на собеседованиях на роль сеньора в JavaScript". И вот что меня там сильно задело, решение данного кода:
console.log([] == ![]); // true
Ниже автор описывает почему в результате истина. Не поленюсь скопировать сюда это безумие:
Раскрыть
Давайте сначала рассмотрим типы обоих операндов:
typeof([]) // "object" typeof(![]) // "boolean"
[] это объект, что ясно. Поскольку все в JavaScript является объектом, включая массивы и функции. Но почему операнд ![] имеет тип boolean? Давайте попробуем разобраться в этом. Когда вы используете! при использовании примитивного значения выполняются следующие преобразования:
* Ложные значения: Если исходное значение является ложным значением (например, false, 0, null, undefined, NaN или пустая строка ''), применение ! преобразует его в значение true.
* Истинные значения: Если исходное значение является истинным значением (любое значение, которое не является ложным), применение ! преобразует его в значение false.
В нашем случае [] — это пустой массив, который является истинным значением в JavaScript. Поскольку [] является истиной, ![] становится ложью. Таким образом, наше выражение становится:
[] == ![]
[] == false
Теперь давайте продвинемся вперед и разберемся с оператором ==. Всякий раз, когда сравниваются 2 значения с использованием оператора ==, JavaScript выполняет Алгоритм Сравнения Абстрактного Равенства. Алгоритм состоит из следующих шагов:

Abstract Equality Comparison Algorithm
Как вы можете видеть, этот алгоритм учитывает типы сравниваемых значений и выполняет необходимые преобразования.
Для нашего случая давайте обозначим x как [], а y как ![]. Мы проверили типы x и y и обнаружили, что x является объектом, а y — boolean. Поскольку y является boolean, а x — объектом, применяется условие 7 из алгоритма сравнения абстрактного равенства:
Если Type(y) – Boolean, верни результат сравнения x == ToNumber(y).
Это означает, что если один из типов является логическим, нам нужно преобразовать его в число перед сравнением. Каково значение ToNumber(y)? Как мы видели, [] — это истинное значение, отрицание делает его false. В результате Number(false) равно 0.
[] == false [] == Number(false) [] == 0
Теперь у нас есть сравнение [] == 0, и на этот раз вступает в игру условие 8:
Если Type(x) является String или Number, а Type(y) — Object, верни результат сравнения x == ToPrimitive(y).
Исходя из этого условия, если один из операндов является объектом, мы должны преобразовать его в примитивное значение. Вот тут-то и появляется алгоритм ToPrimitive. Нам нужно преобразовать x, который равен [], в примитивное значение. Массивы — это объекты в JavaScript. Как мы видели ранее, при преобразовании объектов в примитивы в игру вступают методы valueOf и toString. В этом случае valueOf возвращает сам массив, который не является допустимым примитивным значением. В результате мы переходим к toString для получения выходных данных. Применение метода toString к пустому массиву приводит к получению пустой строки, которая является допустимым примитивом:
[] == 0 [].toString() == 0 "" == 0
Преобразование пустого массива в строку дает нам пустую строку "" и теперь мы сталкиваемся со сравнением: "" == 0.
Теперь, когда один из операндов имеет тип string, а другой — тип number, выполняется условие 5:
Если Type(x) — строка, а Type(y) — число, верни результат сравнения ToNumber(x) == y.
Следовательно, нам нужно преобразовать пустую строку "" в число, которое дает нам 0.
"" == 0 ToNumber("") == 0 0 == 0
Наконец, оба операнда имеют одинаковый тип, и выполняется условие 1. Поскольку оба имеют одинаковое значение, конечный результат равен:
0 == 0 // true
Для начала хочется передать отдельный привет всем тем, кто пишет, что "современный фронтенд - это легко", подразумевая изучение этого выкидыша IT-индустрии - языка JavaScript.
А дальше хочется пофилософствовать. Бог создал человека, даровал ему жизнь и целый необъятный мир в придачу. А ещё порядка 60-80 лет жизни. И что в итоге? В итоге некоторые из них пришли к тому, что выбрали для себя не реальную жизнь, не мир, дарованный Богом, а то, что приведено выше - копание в какой-то нелогичной чертовщине, где одна строчка кода требует объяснения на 3000 символов, а совокупное время на изучение всей этой "науки" - годы жизни, просиженные на заднице возле коробки монитора 30х40.
И чёрт бы с ним, с JavaScript-ом, так ведь почти вся сфера, почти всё IT построено на этом садомазохизме, где нужно прилагать какие-то нечеловеческие усилия в виде постоянного обучения и содержания в голове огромного массива узконаправленной информации. Технологии не становятся легче или логичнее - они лишь преумножаются в своём количестве, валятся как снежный ком с горы, становясь всё более сложными, а вместе с ними растут и требования в вакансиях.
Покажите эту статью вайтишникам, мечтающим писать код "не напрягаясь", пусть десять раз подумают, прежде чем без вазелина лезть в эту сферу.


Комментарии (259)