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