Spec-Zone.ru › JavaScript

Symbol

Базовая поддержка Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и во многих версиях браузеров. Она доступна во всех браузерах с сентября 2015 года.

Symbol — это встроенный объект, конструктор которого возвращает symbol примитивное значение, также называемое значением Symbol или просто Symbol, которое гарантированно является уникальным. Символы часто используют для добавления объекту уникальных ключей свойств, которые не будут конфликтовать с ключами, добавленными в объект другим кодом, и которые скрыты от механизмов, обычно используемых другим кодом для доступа к объекту. Это обеспечивает некоторую слабую инкапсуляцию или слабую форму сокрытия информации.

Каждый вызов Symbol() гарантированно возвращает уникальный Symbol. Каждый вызов Symbol.for("key") всегда возвращает один и тот же Symbol для заданного значения "key". При вызове Symbol.for("key"), если в глобальном реестре Symbol найден Symbol с заданным ключом, возвращается этот Symbol. В противном случае создаётся новый Symbol, добавляется в глобальный реестр Symbol под заданным ключом и возвращается.

Описание

Чтобы создать новый примитивный Symbol, используйте Symbol() и, по желанию, укажите строку в качестве описания:

const sym1 = Symbol();
const sym2 = Symbol("foo");
const sym3 = Symbol("foo");

Приведённый выше код создаёт три новых Symbol. Обратите внимание, что Symbol("foo") не преобразует строку "foo" в Symbol. При каждом вызове создаётся новый Symbol:

Symbol("foo") === Symbol("foo"); // false

Следующий синтаксис с оператором new вызовет TypeError:

const sym = new Symbol(); // TypeError

Это не позволяет авторам создавать явный объект-обёртку Symbol вместо нового значения Symbol. Это может показаться неожиданным, поскольку обычно явные объекты-обёртки для примитивных типов данных создавать можно (например, new Boolean, new String и new Number).

Если вам действительно нужно создать объект-обёртку Symbol, можно использовать функцию Object():

const sym = Symbol("foo");
typeof sym; // "symbol"
const symObj = Object(sym);
typeof symObj; // "object"

Поскольку символы — единственный примитивный тип данных с идентичностью по ссылке (то есть невозможно дважды создать один и тот же символ), в некотором смысле они ведут себя как объекты. Например, они подлежат сборке мусора и поэтому могут храниться в объектах WeakMap, WeakSet, WeakRef и FinalizationRegistry.

Общие символы в глобальном реестре Symbol

Синтаксис, использующий функцию Symbol(), создаёт Symbol, значение которого остаётся уникальным на протяжении всего времени работы программы. Чтобы создавать символы, доступные в разных файлах и даже в разных средах выполнения (каждая из которых имеет собственную глобальную область видимости), используйте методы Symbol.for() и Symbol.keyFor(), чтобы добавлять символы в глобальный реестр Symbol и получать их из него.

Обратите внимание, что «глобальный реестр Symbol» — это лишь условное понятие, которое может не соответствовать какой-либо внутренней структуре данных в движке JavaScript. Даже если такой реестр существует, его содержимое недоступно коду JavaScript, кроме как через методы for() и keyFor().

Метод Symbol.for(tokenString) принимает строковый ключ и возвращает значение Symbol из реестра, а Symbol.keyFor(symbolValue) принимает значение Symbol и возвращает соответствующий ему строковый ключ. Они обратны друг другу, поэтому следующее выражение является true:

Symbol.keyFor(Symbol.for("tokenString")) === "tokenString"; // true

Поскольку зарегистрированные символы могут произвольно создаваться где угодно, они ведут себя почти так же, как строки, которые они оборачивают. Поэтому они не гарантированно уникальны и не подлежат сборке мусора. По этой причине зарегистрированные символы нельзя использовать в объектах WeakMap, WeakSet, WeakRef и FinalizationRegistry.

Общеизвестные символы

Все статические свойства конструктора Symbol сами являются символами, значения которых неизменны в разных средах выполнения. Они называются общеизвестными символами и служат «протоколами» для некоторых встроенных операций JavaScript, позволяя пользователям настраивать поведение языка. Например, если у функции-конструктора есть метод с именем Symbol.hasInstance, этот метод определяет поведение оператора instanceof.

До появления общеизвестных символов JavaScript использовал обычные свойства для реализации некоторых встроенных операций. Например, функция JSON.stringify пытается вызвать метод toJSON() каждого объекта, а функция String вызывает методы объекта toString() и valueOf(). Однако по мере добавления в язык новых операций назначение каждой операции «магического свойства» может нарушить обратную совместимость и затруднить понимание поведения языка. Общеизвестные символы позволяют делать такие настройки «невидимыми» для обычного кода, который обычно считывает только строковые свойства.

Примечание: Раньше в спецификации для обозначения общеизвестных символов использовалась запись @@<symbol-name>. Например, Symbol.hasInstance записывался как @@hasInstance, а метод Array.prototype[Symbol.iterator]() назывался Array.prototype[@@iterator](). Эта запись больше не используется в спецификации, но её всё ещё можно встретить в старой документации или обсуждениях.

К общеизвестным символам неприменимо понятие возможности сборки мусора, поскольку их набор фиксирован и они уникальны на протяжении всего времени работы программы, подобно встроенным объектам, таким как Array.prototype. Поэтому их также можно использовать в объектах WeakMap, WeakSet, WeakRef и FinalizationRegistry.

Поиск свойств Symbol в объектах

Метод Object.getOwnPropertySymbols() возвращает массив символов и позволяет найти свойства Symbol в заданном объекте. Обратите внимание, что при создании у каждого объекта нет собственных свойств Symbol, поэтому массив будет пустым, если вы не добавили объекту свойства Symbol.

Конструктор

Symbol()
Возвращает примитивные значения типа Symbol. При вызове с new выбрасывает ошибку.

Статические свойства

Все статические свойства — это общеизвестные символы. В описаниях этих символов мы будем использовать формулировки вроде «Symbol.hasInstance — это метод, определяющий…», но помните, что речь идёт о семантике метода объекта, имя которого совпадает с этим Symbol (поскольку общеизвестные символы служат «протоколами»), а не об описании самого значения Symbol.

Symbol.asyncDispose
Метод, асинхронно освобождающий ресурсы объекта при выходе объекта из области видимости. Используется объявлением await using.
Symbol.asyncIterator
Метод, возвращающий итератор AsyncIterator по умолчанию для объекта. Используется конструкцией for await...of.
Symbol.dispose
Метод, освобождающий ресурсы объекта при выходе объекта из области видимости. Используется объявлением using.
Symbol.hasInstance
Метод, определяющий, распознаёт ли объект-конструктор другой объект как свой экземпляр. Используется оператором instanceof.
Symbol.isConcatSpreadable
Логическое значение, указывающее, следует ли преобразовать объект в его элементы массива. Используется методом Array.prototype.concat().
Symbol.iterator
Метод, возвращающий итератор по умолчанию для объекта. Используется конструкцией for...of.
Symbol.match
Метод, выполняющий поиск соответствий в строке; также используется для определения того, можно ли использовать объект как регулярное выражение. Используется методом String.prototype.match().
Symbol.matchAll
Метод, возвращающий итератор, который выдаёт совпадения регулярного выражения со строкой. Используется методом String.prototype.matchAll().
Symbol.replace
Метод, заменяющий совпавшие подстроки строки. Используется методом String.prototype.replace().
Symbol.search
Метод, возвращающий индекс в строке, которому соответствует регулярное выражение. Используется методом String.prototype.search().
Symbol.species
Функция-конструктор, используемая для создания производных объектов.
Symbol.split
Метод, разделяющий строку в позициях, соответствующих регулярному выражению. Используется методом String.prototype.split().
Symbol.toPrimitive
Метод, преобразующий объект в примитивное значение.
Symbol.toStringTag
Строковое значение, используемое для описания объекта по умолчанию. Используется методом Object.prototype.toString().
Symbol.unscopables
Объект, имена собственных и унаследованных свойств которого исключаются из привязок окружения with связанного объекта.

Статические методы

Symbol.for()
Ищет в глобальном реестре Symbol зарегистрированные символы с заданным значением key и возвращает найденный. В противном случае создаёт новый Symbol и регистрирует его с помощью key.
Symbol.keyFor()
Получает из глобального реестра Symbol общий ключ Symbol для заданного символа.

Свойства экземпляра

Эти свойства определены в Symbol.prototype и доступны всем экземплярам Symbol.

Symbol.prototype.constructor
Функция-конструктор, создавшая объект экземпляра. Для экземпляров Symbol начальным значением является конструктор Symbol.
Symbol.prototype.description
Строка, доступная только для чтения и содержащая описание Symbol.
Symbol.prototype[Symbol.toStringTag]
Начальное значение свойства [Symbol.toStringTag] — строка "Symbol". Это свойство используется в методе Object.prototype.toString(). Однако, поскольку у Symbol также есть собственный метод toString(), это свойство не используется, если не вызвать Object.prototype.toString.call(), передав символ в качестве thisArg.

Методы экземпляра

Symbol.prototype.toString()
Возвращает строку, содержащую описание Symbol. Переопределяет метод Object.prototype.toString().
Symbol.prototype.valueOf()
Возвращает Symbol. Переопределяет метод Object.prototype.valueOf().
Symbol.prototype[Symbol.toPrimitive]()
Возвращает Symbol.

Примеры

Использование оператора typeof с символами

Оператор typeof помогает распознавать символы.

typeof Symbol() === "symbol";
typeof Symbol("foo") === "symbol";
typeof Symbol.iterator === "symbol";

Преобразование типа Symbol

При преобразовании типа Symbol следует учитывать несколько особенностей.

  • При попытке преобразовать Symbol в число будет выброшена ошибка TypeError (например, +sym или sym | 0).
  • При использовании нестрогого сравнения Object(sym) == sym возвращает true.
  • Symbol("foo") + "bar" вызывает ошибку TypeError (невозможно преобразовать Symbol в строку). Это, например, предотвращает незаметное создание нового строкового имени свойства из Symbol.
  • «Более безопасное» преобразование String(sym) для символов работает как вызов Symbol.prototype.toString(), однако обратите внимание, что new String(sym) вызовет ошибку.

Символы и итерация for...in

Символы не перечисляются при итерациях for...in. Кроме того, Object.getOwnPropertyNames() не возвращает свойства объектов с ключами Symbol, однако для их получения можно использовать Object.getOwnPropertySymbols().

const obj = {};

obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";

for (const i in obj) {
  console.log(i);
}
// "c" "d"

Символы и JSON.stringify()

Свойства с ключами Symbol полностью игнорируются при использовании JSON.stringify():

JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'

Подробнее см. в описании JSON.stringify().

Объекты-обёртки Symbol в качестве ключей свойств

Если объект-обёртка Symbol используется в качестве ключа свойства, он преобразуется в обёрнутый им Symbol:

const sym = Symbol("foo");
const obj = { [sym]: 1 };
obj[sym]; // 1
obj[Object(sym)]; // still 1

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

Спецификация
Спецификация языка ECMAScript® 2027
# sec-symbol-objects

Совместимость с браузерами

Настольные компьютеры Мобильные устройства Сервер
Chrome Edge Firefox Opera Safari Chrome для Android Firefox для Android Opera для Android Safari на iOS Samsung Internet WebView для Android WebView на iOS Bun Deno Node.js
Symbol
38
12В Edge 12 свойства Symbol включались в вывод JSON.stringify().
36
25
9
38
36
25
9
3.0
38
9
1.0.0
1.0
0.12.0
@@toPrimitive
47
15
44
34
10
47
44
34
10
5.0
47
10
1.0.0
1.0
6.0.0
Symbol
38
12
36
25
9
38
36
25
9
3.0
38
9
1.0.0
1.0
0.12.0
asyncDispose
127
127
141
113
предварительная версия
127
141
84
Нет
28.0
127
Нет
1.0.23
1.37
24.0.0
20.4.0–21.0.0Доступно только для ресурсов fs и stream.
18.18.0–19.0.0Доступно только для ресурсов fs и stream.
asyncIterator
63
79
57
50
11.1
63
57
46
11.3
8.0
63
11.3
1.0.0
1.0
10.0.0
description
70
79
63
57
12.1
12–12.1Не поддерживается для описания со значением undefined.
70
63
49
12.2
12–12.2Не поддерживается для описания со значением undefined.
10.0
70
12.2
12–12.2Не поддерживается для описания со значением undefined.
1.0.0
1.0
11.0.0
dispose
125
125
141
111
предварительная версия
125
141
83
Нет
27.0
125
Нет
1.0.23
1.37
24.0.0
20.4.0–21.0.0Доступно только для ресурсов fs и stream.
18.18.0–19.0.0Доступно только для ресурсов fs и stream.
for
40
12
36
27
9
40
36
27
9
4.0
40
9
1.0.0
1.0
0.12.0
hasInstance
50
15
50
37
10
50
50
37
10
5.0
50
10
1.0.0
1.0
6.5.0
isConcatSpreadable
48
15
48
35
10
48
48
35
10
5.0
48
10
1.0.0
1.0
6.0.0
iterator
43
12
36
30
10
43
36
30
10
4.0
43
10
1.0.0
1.0
0.12.0
keyFor
40
12
36
27
9
40
36
27
9
4.0
40
9
1.0.0
1.0
0.12.0
match
50
79
40
37
10
50
40
37
10
5.0
50
10
1.0.0
1.0
6.0.0
matchAll
73
79
67
60
13
73
67
52
13
11.0
73
13
1.0.0
1.0
12.0.0
replace
50
79
49
37
10
50
49
37
10
5.0
50
10
1.0.0
1.0
6.0.0
search
50
79
49
37
10
50
49
37
10
5.0
50
10
1.0.0
1.0
6.0.0
species
51
13
41
38
10
51
41
41
10
5.0
51
10
1.0.0
1.0
6.5.0
split
50
79
49
37
10
50
49
37
10
5.0
50
10
1.0.0
1.0
6.0.0
toPrimitive
47
15
44
34
10
47
44
34
10
5.0
47
10
1.0.0
1.0
6.0.0
toString
38
12
36
25
9
38
36
25
9
3.0
38
9
1.0.0
1.0
0.12.0
toStringTag
49
15
51
36
10
49
51
36
10
5.0
49
10
1.0.0
1.0
6.0.0
unscopables
38
12
48
25
9
38
48
25
9
3.0
38
9
1.0.0
1.0
0.12.0
valueOf
38
12
36
25
9
38
36
25
9
3.0
38
9
1.0.0
1.0
0.12.0

См. также

  • Полифилл Symbol в core-js
  • typeof
  • Типы и структуры данных JavaScript
  • ES6 подробно: символы на hacks.mozilla.org (2015)

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API