--- title: Типы данных JavaScript и структуры данных slug: Web/JavaScript/Data_structures tags: - JavaScript - Типы данных - Учебник translation_of: Web/JavaScript/Data_structures ---
Все языки программирования содержат встроенные типы данных, но они часто отличаются друг от друга в разных языках. Эта статья — попытка описать встроенные структуры (типы) данных, доступные в JavaScript, и их свойства. На их основе строятся другие структуры данных. Когда это возможно, то мы будем сравнивать типы данных в разных языках.
JavaScript является слабо типизированным или динамическим языком. Это значит, что вам не нужно определять тип переменной заранее. Тип определится автоматически во время выполнения программы. Также это значит, что вы можете использовать одну переменную для хранения данных различных типов:
var foo = 42; // сейчас foo типа Number foo = "bar"; // а теперь foo типа String foo = true; // foo становится типа Boolean
Стандарт ECMAScript определяет 9 типов:
typeof instance === "undefined"
typeof instance === "boolean"
typeof instance === "number"
typeof instance === "string"
typeof instance === "bigint"
typeof instance === "symbol"
typeof instance === "object"
. Специальный примитив, используемый не только для данных но и в качестве указателя на финальную точку в Цепочке Прототипов;typeof instance === "object"
. Простая структура, используемая не только для хранения данных, но и для создания других структур, где любая структура создаётся с использованием ключевого слова new
: new Object, new Array, new Map, new Set, new WeakMap, new WeakSet, new Date и множество других структур;typeof instance === "function"
. Специальный случай, упрощающий определение типа для Функций, несмотря на то, что все функции конструктивно унаследованы от Object.И здесь нам необходимо сделать предостережение относительно использования оператора typeof
для определения типа структур, т.к. все структуры будут возвращать "object"
при его использовании, так как назначение typeof
-- проверка типа данных, но не структур. Если проверить тип структуры всё же необходимо, то в этом случае желательно использовать оператор instanceof, так как именно он отвечает на вопрос о том, какой конструктор был использован для создания структуры.
Все типы данных в JavaScript, кроме объектов, являются иммутабельными (значения не могут быть модифицированы, а только перезаписаны новым полным значением). Например, в отличии от C, где строку можно посимвольно корректировать, в JavaScript строки пересоздаются только полностью. Значения таких типов называются «примитивными значениями».
Булевый тип представляет логическую сущность и имеет два значения: true (истина)
и false (ложь)
. Смотрите {{Glossary("Boolean")}} и {{jsxref("Boolean")}} для получения подробностей.
Этот тип данных имеет всего одно значение: null
. Смотрите {{jsxref("null")}} и {{Glossary("Null")}} для получения подробностей.
Переменная, которой не было присвоено значение, будет иметь значение 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 являются иммутабельными. Это означает, что после того, как строковое значение создано, его нельзя модифицировать. Остаётся лишь создать новую строку путём совершения некой операции над исходной строкой. Например:
+
) или метод {{jsxref("String.concat()")}}.Иногда может показаться соблазнительным использование строк для представления сложных структур данных. Это даст небольшие краткосрочные выгоды:
Несмотря на то, что в строке можно выразить данные любой сложности, делать это — не самая лучшая идея. Например, используя разделитель, строку можно использовать как список элементов (массив JavaScript будет более подходящим решением). К сожалению, если такой сепаратор встретится в значении одного из элементов, такой список будет сломан. Выходом может стать добавление символа экранирования, и т. д. Всё это потребует добавления множества ненужных правил, и станет обременительным при поддержке.
Используйте строки только для текстовых данных. Для составных структур преобразуйте строки в подобающие конструкции.
Символы являются нововведением JavaScript начиная с ECMAScript 2015. Символ — это уникальное и иммутабельное примитивное значение, которое может быть использовано как ключ для свойства объекта (смотрите ниже). В некоторых языках программирования символы называются атомами. Их также можно сравнить с именованными значениями перечисления (enum) в языке C. Подробнее смотрите {{Glossary("Symbol")}} и {{jsxref("Symbol")}}.
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 |
Атрибут | Тип | Описание |
---|---|---|
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)}}
Эти наборы данных используют ссылку на объект в качестве ключа, и введены в 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 (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')}} |