Как выполняется цикл с условием сравнения строки и числа в JavaScript?
Что проверяют
Понимаете ли вы, как JavaScript приводит типы в условии цикла, и можете ли предсказать число итераций без запуска кода. Типичный следующий вопрос: сколько раз выполнится for (let i = 0; i < "10"; i++) и что изменится, если справа будет строка "abc".
Как отвечать
Условие цикла вычисляется перед каждой итерацией заново, и приведение типов происходит каждый раз. Правила сравнения:
<,>,<=,>=со строкой и числом: строка превращается в число.i < "5"работает какi < 5, цикл пройдёт пять раз;- строка, которая не читается как число:
"abc"и"5px"даютNaN, любое сравнение сNaNложно, цикл не выполнится ни разу; - пустая строка и пробелы: превращаются в
0, поэтомуi < ""тоже даёт ноль итераций; - две строки: сравниваются посимвольно, а не как числа.
"10" < "9"истинно, отсюда классический баг со значениями изinput.value; ==и===: нестрогое равенство приводит типы,"5" == 5истинно, строгое нет. Строгих версий<и>в языке нет, поэтому для них тип нужно привести самому.
Отдельная ловушка с инкрементом. Если счётчик начать со строки let i = "0", то i++ превратит его в число и всё будет работать, а i += 1 склеит строки: "01", затем "011". Сравнение "011" < 5 уже ложно, и цикл отработает два раза вместо пяти.
Хороший ответ заканчивается рекомендацией: приводить данные явно на входе через Number(value) или parseInt(value, 10) и проверять результат Number.isNaN. В проекте на TypeScript сравнение числа со строкой просто не пройдёт проверку типов.
Где спотыкаются
Считают, что === делает строгим и сравнение <. На деле строгий оператор влияет только на равенство, а < всегда приводит типы.
Путают Number и parseInt. parseInt("5px", 10) вернёт 5, Number("5px") вернёт NaN, а Number("") вернёт 0, из-за чего пустое поле формы молча превращается в ноль.
Сравнивают два значения из полей формы напрямую. Обе стороны строки, сравнение лексикографическое, и "10" < "9" даёт неверный порядок, пока хотя бы одну сторону не привести к числу.