Как объявить a, чтобы выражение было истинным? Что при этом происходит?
a == 1 && a == 2 && a == 3; // true
Ответ
var a = (function () { let val = 0; return { valueOf: () => { val++; return val; }, };})();a == 1 && a == 2 && a == 3; // true
При нестрогом сравнении == объект приводится к примитиву через valueOf (сначала пробуется Symbol.toPrimitive, затем valueOf, затем toString). Наш valueOf — с побочным эффектом: увеличивает счётчик и возвращает новое значение при каждом вызове. Три сравнения дают 1, 2, 3 — все истинны.
Разбор
Пошаговый разбор
Шаг
Что происходит
Значение
a == 1
== вызывает a.valueOf() → val = 1
1 == 1 → true
a == 2
valueOf() снова → val = 2
2 == 2 → true
a == 3
valueOf() снова → val = 3
3 == 3 → true
Ключевая идея
== запускает приведение типов; у объектов оно проходит через valueOf/toString. Побочный эффект внутри valueOf позволяет объекту «менять» своё значение между сравнениями. Со строгим === трюк не сработал бы — там нет приведения.