Типы данных в JS — это один из наиболее часто задаваемых вопросов на собеседованиях. Неудивительно, ведь в JavaScript всё строится вокруг типов данных, так как именно с ними взаимодействует наша программа. В этой статье рассмотрим все доступные типы данных и их различия.
Статья из цикла
Эта статья входит в цикл материалов курса по JavaScript. Советы по способу изучения материала можно найти здесь.
Теория хорошо описана в следующих источниках:
Практические задания можно найти здесь:
- Присвойте значение 7 переменной “a”.
- Присвойте содержимое “a” переменной “b”.
- Определите переменную “a” с помощью var и инициализируйте ее значением 9.
- Инициализируйте три переменные “a”, “b” и “c” значениями 5, 10 и «I am a» соответственно, чтобы они не были неопределенными.
- Измените существующие объявления и присваивания так, чтобы в их именах использовался camelCase. Не создавайте новых переменных.
Типы данных в JS
На момент создания данного материала язык EcmaScript насчитывает 8 типов данных.
Семь примитивных:
- Undefined;
- Null;
- Boolean;
- Два числовых типа – Number и BigInt – для работы с большими числами;
- String;
- Symbol.
И один составной или, как его еще называют, сложный тип – Object.
Небольшое примечание: дальше я буду использовать термин «переменная». Эту тему мы разберем немного позже, а пока я хочу, чтобы вы узнали о переменных следующее:
- Переменные создаются для того, чтобы хранить в них данные. Создание переменной называют объявлением переменной.
- При объявлении переменной мы даем ей имя для того, чтобы к этим данным можно было обратиться в будущем.
Семь примитивных типов, один составной. В чем же разница?
И примитивные типы данных, и объекты хранятся в памяти. Но, при присваивании их в виде значения другой переменной, ведут себя по-разному. Примитивы копируются, а в случае с объектами записывается ссылка, по которой можно получить значение этого объекта. То есть при копировании объектов копируется не сам объект, а ссылка на него.
Это поведение поначалу может сбить с толку, но не волнуйтесь, мы разберем его на примере немного позже.
Определить, с каким типом данных мы сейчас имеем дело, поможет оператор typeof. Если мы передадим ему какое-нибудь значение или переменную, в которой хранится значение, он вернет нам название типа данных.
Мы передаем этому оператору значения разных типов, чтобы посмотреть возвращаемое значение.
typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof "42" === "string"; // true
typeof 42 === "number"; // true
// "were introduced in ES6 and are also primitives"
typeof BigInt("9007199254740991") === "bigint"; // true
typeof Symbol() === "symbol"; // true
Несколько слов о каждом из типов
- Undefined – говорит о том, что значение – неопределенное. Вы получите его, если передадите оператору typeof только что объявленную пустую переменную.
- Boolean – булевый тип данных, имеющий два значения true и false, то есть правда или ложь. Это может быть результатом сравнения двух чисел, например, пять больше трех? Да, утверждение верное, результатом сравнения будет true.
- String – представляет строки.
- Number – числовой тип данных. Он подразумевает как целые числа, так и числа с плавающей точкой. Переменная типа Number может хранить в себе 20-значное число, но если этого оказывается недостаточно, на помощь придет BigInt, который был создан для работы с большими числами.
- Symbol – это уникальный и неизменяемый тип данных, который может быть использован как идентификатор для свойств объектов. О нем мы поговорим в другой статье.
BigInt и Symbol были добавлены в язык в 2015 году. В частности, из-за этого вы можете встретить в интернете информацию о меньшем количестве типов данных в языке.
- Null – говорит о том, что значение отсутствует, но тем не менее определено. Если вы хотите очистить какую-нибудь переменную от значения, вы присваиваете ей null.
У null есть одна особенность. Оператор typeof при его проверке возвращает object. Это ошибка языка, и она вряд ли будет когда-то исправлена, так как в интернете существует масса кода подстроенного под эту особенность.
Что касается объектов и подтипов объекта, таких как: функции и массивы, мы разберем каждый из них в следующих статьях. Сейчас же просто посмотрим на их синтаксис. Вы часто будете встречать их на разных сайтах, так что будет лучше, если вы узнаете немного о них уже сейчас.
Объекты
Хранилища данных представлены в виде пар «ключ-значение». Ключи называют свойствами. Объектами удобно описывать сущности из нашего мира. Например, какого-нибудь пользователя, у которого есть имя, фамилия и телефон. В нашем примере мы создали объект с помощью литерала объекта (фигурные скобки сразу после знака равно).
var user = {
firstName: 'John',
lastName: 'Dou',
phone: '555-24-42',
}
typeof user === "object"; // true
user.firstName // John
user['firstName'] // John
Из проверки с помощью typeof видно, что мы имеем дело с объектом. Получить значение свойства объекта можно через обращение к нему через точку после имени переменной или, указав имя свойства в квадратных скобках.
Функции
Одной из ключевых особенностей функций является переиспользование кода. Идея заключается в том, что мы выносим в них код, который необходимо выполнить несколько раз в программе, и вызываем эту функцию там, где это необходимо.
Одним из способов создания функции является объявление с помощью ключевого слова function, после которого идет имя функции. Тело функции определяется в фигурных скобках. Вызвать функцию можно по ее имени, после чего идут круглые скобки. Проверка с помощью оператора typeof вернет нам function, а это может навести на мысль, что функции – это отдельный тип данных. В действительности же функции являются подтипом объекта и называются вызываемым объектом (callable object).
Познакомившись с функциями ближе, можно заметить, что с ними действительно можно обращаться, как с объектами. Например, у них есть свойство “length”, к которому можно обратится через точку после имени переменной, как мы делали это в объекте. Это свойство говорит о количество аргументов функции (переданные данные). В нашем примере вернется ноль.
function a() {
// function code is defined here
}
a();
typeof a === 'function' //true
a.length; // 0
Массивы
И, наконец, массивы.
Массив, как и функция, является подтипом объекта. Массивы также используются как хранилище данных и могут хранить в себе элементы разных типов, даже другие массивы. В примере ниже мы объявили массив с помощью литерала массива (квадратные скобки после знака равно) и сразу же определили в нем три элемента: число, строку и другой массив. Из проверки с помощью typeof видно, что мы имеем дело с объектом.
var a = [ 1, "2", [3] ];
typeof a === "object"; // true
// an array element can be retrieved using its index (number in order). The calculation starts from zero.
a[0] // 1
Каждому элементу, сохраненному в массив, присваивается индекс (его номер по порядку, начиная с ноля). В дальнейшем элемент массива может быть получен по этому индексу. В нашем примере мы запрашиваем первый элемент массива. Для этого используем квадратные скобки после имени переменной, в которые передаем необходимый индекс, то есть ноль.
Как вы могли заметить, массивы – это упорядоченные коллекции. И чаще всего они используются тогда, когда нужно перебрать и обработать все элементы какого-нибудь списка.
И, наконец, живой пример, который показывает, как в коде используются разные типы данных. Пример иллюстрирует очередь людей. Так как очередь имеет четкий порядок (каждый человек стоит друг за другом), для ее описания удобнее всего использовать массив.
var userQueue = [
{fullName: 'John Dou'},
{fullName: 'Martha Stuart'},
{fullName: 'Sam Sparks'}
];
let fisrtUserInQueue = userQueue[0];
Каждый человек здесь представлен объектом со свойством “fullName” (полное имя). Значением этого свойства является строка (примитивный тип). Для получения первого человека в очереди мы используем индекс 0.