--- title: Типы данных JavaScript и структуры данных slug: Web/JavaScript/Data_structures tags: - JavaScript - Типы данных - Учебник translation_of: Web/JavaScript/Data_structures ---
{{jsSidebar("More")}}

Все языки программирования содержат встроенные типы данных, но они часто отличаются друг от друга в разных языках. Эта статья — попытка описать встроенные структуры (типы) данных, доступные в JavaScript, и их свойства. На их основе строятся другие структуры данных. Когда это возможно, то мы будем сравнивать типы данных в разных языках.

Динамическая типизация

JavaScript является слабо типизированным или динамическим языком. Это значит, что вам не нужно определять тип переменной заранее. Тип определится автоматически во время выполнения программы. Также это значит, что вы можете использовать одну переменную для хранения данных различных типов:

var foo = 42; // сейчас foo типа Number
foo = "bar"; // а теперь foo типа String
foo = true;  // foo становится типа Boolean

Типы данных

Стандарт ECMAScript определяет 9 типов:

И здесь нам необходимо сделать предостережение относительно использования оператора typeof для определения типа структур, т.к. все структуры будут возвращать "object" при его использовании, так как назначение typeof -- проверка типа данных, но не структур. Если проверить тип структуры всё же необходимо, то в этом случае желательно использовать оператор instanceof, так как именно он отвечает на вопрос о том, какой конструктор был использован для создания структуры.

Примитивные значения

Все типы данных в JavaScript, кроме объектов, являются иммутабельными (значения не могут быть модифицированы, а только перезаписаны новым полным значением). Например, в отличии от C, где строку можно посимвольно корректировать, в JavaScript строки пересоздаются только полностью. Значения таких типов называются «примитивными значениями».

Булевый тип данных

Булевый тип представляет логическую сущность и имеет два значения: true (истина) и false (ложь). Смотрите {{Glossary("Boolean")}} и {{jsxref("Boolean")}} для получения подробностей.

Null

Этот тип данных имеет всего одно значение: null. Смотрите {{jsxref("null")}} и {{Glossary("Null")}} для получения подробностей.

Undefined

Переменная, которой не было присвоено значение, будет иметь значение undefined. Смотрите {{jsxref("undefined")}} и {{Glossary("undefined")}} для получения подробностей.

Числа

В соответствии со стандартом ECMAScript, существует только один числовой тип, который представляет собой 64-битное число двойной точности согласно стандарту IEEE 754. Другими словами, специального типа для целых чисел в JavaScript нет. Это означает, что при числовых операциях вы можете получить неточное (округлённое) значение. В дополнение к возможности представлять числа с плавающей запятой, есть несколько символических значений: +Infinity (положительная бесконечность), -Infinity (отрицательная бесконечность), и NaN (не число).

Для получения самого большого или самого меньшего доступного значения в пределах +/-Infinity, можно использовать константы {{jsxref("Number.MAX_VALUE")}} или {{jsxref("Number.MIN_VALUE")}}. А начиная с ECMAScript 2015, вы также можете проверить, находится ли число в безопасном для целых чисел диапазоне, используя метод {{jsxref("Number.isSafeInteger()")}}, либо константы {{jsxref("Number.MAX_SAFE_INTEGER")}} и {{jsxref("Number.MIN_SAFE_INTEGER")}}. За пределами этого диапазона операции с целыми числами будут небезопасными, и возвращать приближённые значения.

Ноль в JavaScript имеет два представления: -0 и +0. («0» это синоним +0). На практике это имеет малозаметный эффект. Например, выражение +0 === -0 является истинным. Однако, это может проявиться при делении на ноль:

> 42 / +0
Infinity
> 42 / -0
-Infinity

Хотя число в большинстве случаев представляет только своё значение, JavaScript предоставляет несколько бинарных операций. Они могут использоваться для того, чтобы представлять число как несколько булевых значений, с помощью битовой маски. Это считается плохой практикой, так как JavaScript предлагает другие способы представления булевых значений (например, массив элементов с булевыми значениями или объект, содержащий набор булевых свойств). Кроме того, битовые маски часто делают код более трудным для чтения, понимания и дальнейшей поддержки. Эта техника может быть необходима в условиях технических ограничений, таких как объём локального хранилища данных, или в такой экстремальной ситуации, когда каждый бит передаваемый по сети на счету. Данный подход следует использовать как крайнюю меру, когда не остаётся других путей для необходимой оптимизации.

Текстовые строки

В JavaScript для представления текстовых данных служит тип {{jsxref("Global_Objects/String", "String")}}. Он представляет собой цепочку «элементов» 16-битных беззнаковых целочисленных значений. Каждый такой элемент занимает свою позицию в строке. Первый элемент имеет индекс 0, следующий — 1, и так далее. Длина строки — это количество элементов в ней.

В отличие от языков подобных C, строки в JavaScript являются иммутабельными. Это означает, что после того, как строковое значение создано, его нельзя модифицировать. Остаётся лишь создать новую строку путём совершения некой операции над исходной строкой. Например:

Избегайте повсеместного использования строк в своём коде!

Иногда может показаться соблазнительным использование строк для представления сложных структур данных. Это даст небольшие краткосрочные выгоды:

Несмотря на то, что в строке можно выразить данные любой сложности, делать это — не самая лучшая идея. Например, используя разделитель, строку можно использовать как список элементов (массив JavaScript будет более подходящим решением). К сожалению, если такой сепаратор встретится в значении одного из элементов, такой список будет сломан. Выходом может стать добавление символа экранирования, и т. д. Всё это потребует добавления множества ненужных правил, и станет обременительным при поддержке.

Используйте строки только для текстовых данных. Для составных структур преобразуйте строки в подобающие конструкции.

Тип данных Символ (Symbol)

Символы являются нововведением JavaScript начиная с ECMAScript 2015. Символ — это уникальное и иммутабельное примитивное значение, которое может быть использовано как ключ для свойства объекта (смотрите ниже). В некоторых языках программирования символы называются атомами. Их также можно сравнить с именованными значениями перечисления (enum) в языке C. Подробнее смотрите {{Glossary("Symbol")}} и {{jsxref("Symbol")}}.

Тип данных Большое целое (BigInt)

BigInt является встроенным объектом, который предоставляет способ представления целых чисел, которые больше 2 53, что является наибольшим числом, которое JavaScript может надёжно представить с помощью Number примитива.

> let bigInt = 19241924124n;
> console.log(bigInt);
19241924124n
> console.log(typeof bigInt);
"bigint"

Объекты

В компьютерной терминологии, объект — это значение в памяти, на которое возможно сослаться с помощью {{Glossary("Identifier", "идентификатора")}}.

Свойства

В JavaScript объект может расцениваться как набор свойств. Литеральная инициализация объекта задаёт определённое количество начальных свойств, и в процессе работы приложения поля могут добавляться и удаляться. Значения свойств могут иметь любой тип, включая другие объекты, что позволяет строить сложные, разветвлённые иерархии данных. Каждое свойство объекта идентифицируется ключом, в качестве которого может выступать значение с типом Строка или Символ.

Есть два типа свойств: свойство-значение и свойство-акцессор (свойство, обёрнутое в геттер и сеттер). Они отличаются определёнными атрибутами.

Свойство-значение

Ассоциирует ключ со значением, и имеет следующие атрибуты:

Атрибуты свойства-значения
Атрибут Тип Описание Значение по умолчанию
[[Value]] Любой тип JavaScript Значение, возвращаемое при обращении к свойству. undefined
[[Writable]] Boolean Если false, то [[Value]] свойства не может быть изменено. false
[[Enumerable]] Boolean Если true, свойство будет перечислено в цикле for...in. Смотрите подробнее Перечисляемость и владение свойствами. false
[[Configurable]] Boolean Если false, то свойство не может быть удалено, а его атрибуты, кроме [[Value]] и [[Writable]] не могут быть изменены. false
Устаревшие атрибуты (присутствуют в ECMAScript 3, но переименованы в ECMAScript 5)
Атрибут Тип Описание
Read-only Boolean Зарезервировано по атрибуту [[Writable]] ES5.
DontEnum Boolean Зарезервировано по атрибуту [[Enumerable]] ES5.
DontDelete Boolean Зарезервировано по атрибуту [[Configurable]] ES5.

Свойство-акцессор

Ассоциирует ключ с одной из двух функций-акцессоров (геттер и сеттер) для получения или изменения значения свойства, и имеет следующий атрибуты:

Атрибуты свойства-акцессора
Атрибут Тип Описание Значение по умолчанию
[[Get]] Function или undefined Функция вызывается без параметров и возвращает значение свойства каждый раз, когда происходит чтение свойства. Смотрите также get. undefined
[[Set]] Function или undefined Функция вызывается с одним аргументом, содержащим присваиваемое значение, каждый раз, когда происходит попытка присвоить свойству новое значение. Смотрите также set. undefined
[[Enumerable]] Boolean Если true, свойство будет перечислено в цикле for...in. false
[[Configurable]] Boolean Если false, то свойство не может быть удалено, и не может быть преобразовано в свойство-значение. false

Примечание: Атрибуты обычно используются движком JavaScript, поэтому вы не можете обратиться к ним напрямую (смотрите подробнее Object.defineProperty()). Вот почему в таблицах выше они помещены в двойные квадратные скобки вместо одиночных.

«Обычные» объекты и функции

Объект JavaScript — это таблица соотношений между ключами и значениями. Ключи — это строки (или {{jsxref("Symbol")}}), а значения могут быть любыми. Это делает объекты полностью отвечающими определению хеш-таблицы.

Функции — это обычные объекты, имеющие дополнительную возможность быть вызванными для исполнения.

Даты

Для работы с датами служит встроенный глобальный объект Date.

Массивы общие и типизированные

Массив — это обычный объект с дополнительной связью между целочисленными ключами его свойств и специальным свойством length. Вдобавок ко всему, массивы наследуют Array.prototype, предоставляющий исчерпывающий набор методов для манипуляции массивами. Например, метод indexOf (служит для поиска значения в массиве), push (добавляет элемент в конец массива) и т. д. Всё это делает массив идеальным кандидатом для представления списков и перечислений.

Типизированный массив является новинкой ECMAScript Edition 6 и является массивоподобным представлением для лежащего в его основе бинарного буфера памяти. Следующая таблица поможет вам найти соответствующие типы языка C:

{{page("/ru/docs/Web/JavaScript/Reference/Global_Objects/TypedArray", "Объекты_TypedArray", "", 0, 3)}}

Коллекции: Maps, Sets, WeakMaps, WeakSets

Эти наборы данных используют ссылку на объект в качестве ключа, и введены в JavaScript с приходом ECMAScript Edition 6. {{jsxref("Set")}} и {{jsxref("WeakSet")}} являют собой набор уникальных объектов, в то время как {{jsxref("Map")}} и {{jsxref("WeakMap")}} ассоциируют с объектом (выступающим в качестве ключа) некоторое значение. Разница между Map и WeakMap заключается в том, что только у Map ключи являются перечисляемыми. Это позволяет оптимизировать сборку мусора для WeakMap.

Можно было бы написать собственную реализацию Map и Set на чистом ECMAScript 5. Однако, так как объекты нельзя сравнивать на больше или меньше, то производительность поиска в самодельной реализации будет вынужденно линейной. Нативная реализация (включая WeakMap) имеет производительность логарифмически близкую к константе.

Обычно, для привязки некоторых данных к узлу DOM, приходится устанавливать свойства этому узлу непосредственно, либо использовать его атрибуты data-*. Обратной стороной такого подхода является то, что эти данные будут доступны любому скрипту, работающему в том же контексте. Maps и WeakMaps дают возможность приватной привязки данных к объекту.

Структурированные данные: JSON

JSON (JavaScript Object Notation) — это легковесный формат обмена данными, происходящий от JavaScript, но используемый во множестве языков программирования. JSON строит универсальные структуры данных. Смотрите {{Glossary("JSON")}} и {{jsxref("JSON")}} для детального изучения.

Больше объектов и стандартная библиотека

JavaScript имеет стандартную библиотеку встроенных объектов. Пожалуйста, обратитесь к справочнику, чтобы найти описание всех объектов доступных для работы.

Определение типов оператором typeof

Оператор typeof может помочь определить тип вашей переменной. Смотрите страницу документации, где приведены его детали и случаи использования.

Спецификации

Спецификация Статус Комментарий
{{SpecName('ES1')}} {{Spec2('ES1')}} Начальное определение.
{{SpecName('ES5.1', '#sec-8', 'Типы')}} {{Spec2('ES5.1')}}
{{SpecName('ES6', '#sec-ecmascript-data-types-and-values', 'Типы данных и значения ECMAScript')}} {{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-ecmascript-data-types-and-values', 'Типы данных и значения ECMAScript')}} {{Spec2('ESDraft')}}

Смотрите также