Система преобразования типов в JavaScript очень проста, но отличается от других языков. Поэтому она часто служит «камнем преткновения» для приходящих из других языков программистов.
Всего есть три преобразования:
Эта глава описывает преобразование только примитивных значений, объекты разбираются далее.
Строковое преобразование происходит, когда требуется представление чего-либо в виде строки. Например, его производит функция alert.
Можно также осуществить преобразование явным вызовом String(val):
Как видно из примеров выше, преобразование происходит наиболее очевидным способом, «как есть»: false становится "false", null – "null", undefined – "undefined" и т.п.
Также для явного преобразования применяется оператор "+", у которого один из аргументов строка. В этом случае он приводит к строке и другой аргумент, например:
Численное преобразование происходит в математических функциях и выражениях, а также при сравнении данных различных типов (кроме сравнений ===, !==).
Для преобразования к числу в явном виде можно вызвать Number(val), либо, что короче, поставить перед выражением унарный плюс "+":
| Значение | Преобразуется в... |
|---|---|
undefined | NaN |
null | 0 |
true / false | 1 / 0 |
| Строка | Пробельные символы по краям обрезаются. Далее, если остаётся пустая строка, то 0, иначе из непустой строки "считывается" число, при ошибке результат NaN. |
Например:
Ещё примеры:
Логические значения:
Сравнение разных типов – значит численное преобразование:
При этом строка "\n0" преобразуется к числу, как указано выше: начальные и конечные пробелы обрезаются, получается строка "0", которая равна 0.
С логическими значениями:
Здесь сравнение "==" снова приводит обе части к числу. В первой строке слева и справа получается 0, во второй 1.
Посмотрим на поведение специальных значений более внимательно.
Интуитивно, значения null/undefined ассоциируются с нулём, но при преобразованиях ведут себя иначе.
Специальные значения преобразуются к числу так:
| Значение | Преобразуется в... |
|---|---|
undefined | NaN |
null | 0 |
Это преобразование осуществляется при арифметических операциях и сравнениях > >= < <=, но не при проверке равенства ==. Алгоритм проверки равенства для этих значений в спецификации прописан отдельно (пункт 11.9.3). В нём считается, что null и undefined равны "==" между собой, но эти значения не равны никакому другому значению.
Это ведёт к забавным последствиям.
Например, null не подчиняется законам математики – он «больше либо равен нулю»: null>=0, но не больше и не равен:
Значение undefined вообще «несравнимо»:
Для более очевидной работы кода и во избежание ошибок лучше не давать специальным значениям участвовать в сравнениях > >= < <=.
Используйте в таких случаях переменные-числа или приводите к числу явно.
Преобразование к true/false происходит в логическом контексте, таком как if(value), и при применении логических операторов.
Все значения, которые интуитивно «пусты», становятся false. Их несколько: 0, пустая строка, null, undefined и NaN.
Остальное, в том числе и любые объекты – true.
Полная таблица преобразований:
| Значение | Преобразуется в... |
|---|---|
undefined, null | false |
| Числа | Все true, кроме 0, NaN -- false. |
| Строки | Все true, кроме пустой строки "" -- false |
| Объекты | Всегда true |
Для явного преобразования используется двойное логическое отрицание !!value или вызов Boolean(value).
"0" становится trueВ отличие от многих языков программирования (например PHP), "0" в JavaScript является true, как и строка из пробелов:
Логическое преобразование интересно тем, как оно сочетается с численным.
Два значения могут быть равны, но одно из них в логическом контексте true, другое – false.
Например, равенство в следующем примере верно, так как происходит численное преобразование:
… А в логическом контексте левая часть (0) даст false, правая ("\n0\n") – true, так как любая не пустая строка в логическом контексте равна true:
С точки зрения преобразования типов в JavaScript это совершенно нормально. При сравнении с помощью «==» – численное преобразование, а в if – логическое, только и всего.
В JavaScript есть три преобразования:
String(value) – в строковом контексте или при сложении со строкой. Работает очевидным образом.Number(value) – в численном контексте, включая унарный плюс +value. Происходит при сравнении разных типов, кроме строгого равенства.Boolean(value) – в логическом контексте, можно также сделать двойным НЕ: !!value.Точные таблицы преобразований даны выше в этой главе.
Особым случаем является проверка равенства с null и undefined. Они равны друг другу, но не равны чему бы то ни было ещё, этот случай прописан особо в спецификации.