Типы данных в Javascript (особенности)
Данная статья предназначена для WebUI программистов, или людей работающих с JS кодом, которые хотят полностью разобраться с особенностью типов данных JS.
Согласно 5-той редакции ECMAscript (http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf стр. 28) существует 6 типов данных:
undefined, null, Boolean, String, Number,Object
.
Прежде чем мы приступим, обращая внимание что в JS существует два типа сравнения:
== — два знака
=== — три знака
разница между ними в том, что первый вариант делает сравнение типов данных с приведением типа,
в то время как второй — без приведение типа. То есть выходить, что
второй вариант проверяет и тип и значение, в то время как первый
вариант проверяет лишь значение.
Итак, продолжим. Начнем с двух типов данных которые наибольшие «конфюзят» разработчиков: undefined
и null
.
undefined
и null
грубо говоря чем-то похожи между собой, ну хотя бы тем, что оба они предназначены для отображения чего-то неопределенного или несуществующего.
Рассмотрим такой пример:
undefined == null; // true
Заметьте, что сдесь мы применили два знака равно. Но на самом деле, undefined
и null
это разные вещи:
undefined === null; // false
Теперь я попытаюсь объяснить, зачем же было придумано два типа, вроде делающих одно и то же.
Давайте начнем с того, что такое вообще undefined.
Это тип данных, который означает не определенный (не установленный).
Такой тип данных очень легко получить, просто объявив переменную.
var a; // undefined
или
var a = undefined; // то же самое
typeof a; // undefined
Как видно с примера, если значение равняется undefined
, это значит что переменная существует (иначе было бы исключение ReferenceError
), но она не определена никаким значением, соответственно у нее автоматически стает тип undefined
. Все предельно просто. Так зачем же тогда null
? Это мы увидим дальше…
Согласно ECMAscript
спецификации, если мы обращаемся к несуществующему ключу объекта, мы должны получить undefined
.
var o = { x: 1, y: 2 }; o.z; // undefined typeof o.z; // undefined
Тут все просто, нету ключа, возвращается undefined
.
Но как же быть если у меня ключ есть, а тип как раз undefined
?
var o = { x: 1, y: 2, z: undefined }; o.z; // undefined typeof o.z; // undefined
Как мы видим результат один и тот же.
Вот тут на и поможет null
.
var o = { x: 1, y: 2, z: null }; o.z; // null typeof o.z; // object <-- опа!
Как видим, null
нам помог в том, чтобы явно указать что ключ существует, но с типом null
.
Вообще-то более культурным способом проверки ключа в объекте является «in»
"z" in o; // true
В не зависимости от того будет ключ стоять в undefined
или null
он вернет true
.
Так зачем же тогда null
? Риторический вопрос. Хорошим тоном программирования является использовать undefined
для простых типов, а nul
l для объектов. Если в ответ я получаю null
, это значит что предо мной будущий объект. Если же я получаю undefined
это должно было быть какое-то значение, либо string
либо number
.
Это не аксиома но правила хорошего тона.
А теперь интересные примеры:
undefined == null; // true !!undefined == !!null; // true !!undefined == false; // true !!undefined == 0; // true undefined == false; // false "undefined" == undefined; // false !!undefined + null + 0; // 0
И так подведем итоги. undefined
— создан для указания неопределенного типа данных (то есть фактически без типа), в то время как null
для указания несуществующей ссылки или объекта.
В предыдущем примере можно было заметить, что null
определился как объект. Это бага JS которая тянется с ранних версий. Ее
уже не фиксают, чтобы не ломать совместимость с предыдущими версиями.
Теперь еще один интересный случай. function
.
function f(){}
typeof f; // function <– вот это да
Оказывается есть еще тип данных как ф-ция? Нет. На самом деле ф-ция является объектом с импламентнутым методом Call
.
var a = []; typeof a; // object
Вот тут все OK. Массив и на самом деле является объектом. В то время
как объект в некотором роде можно рассматривать как ассоциативный
массив.
bclary.com/2004/11/07/#a-13.2.1
bclary.com/2004/11/07/#a-11.4.3
javascript.crockford.com/remedial.html
wiki.ecmascript.org/doku.php?id=proposals:typeof