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
Спецификации
Совместимость с браузерами
| Настольные компьютеры | Мобильные устройства | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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