Обзор

ES6 вводит новый примитивный тип данных Symbol, который представляет уникальные значения. Его наиболее важный сценарий использования — определение уникальных имён свойств для объектов.

Помимо Number, String, Boolean, Object, null и undefined, типы данных ES6 также включают Symbol.


Базовое использование

Функцию Symbol нельзя использовать с командой new, потому что Symbol — это примитивный тип данных, а не объект. Она может принимать строку в качестве параметра, чтобы задать описание для только что созданного Symbol; это описание используется для отображения в консоли или при преобразовании в строку, чтобы их было легче различать.

let sy = Symbol("KK"); console.log(sy); // Symbol(KK) typeof(sy); // "symbol" //Значения, возвращаемые Symbol() с одним и тем же параметром, не равны. let sy1 = Symbol("kk"); sy === sy1; // false

Сценарии использования

В качестве имён свойств

Использование

Поскольку каждое значение Symbol уникально, использование Symbol в качестве имени свойства объекта позволяет гарантировать, что имена свойств не будут конфликтовать.

let sy = Symbol("key1"); //Синтаксис 1 let syObject = {}; syObject[sy] = "kk"; console.log(syObject); // {Symbol(key1): "kk"} //Синтаксис 2 let syObject = { [sy]: "kk" }; console.log(syObject); // {Symbol(key1): "kk"} //Синтаксис 3 let syObject = {}; Object.defineProperty(syObject, sy, {value: "kk"}); console.log(syObject); // {Symbol(key1): "kk"}

Когда Symbol используется в качестве имени свойства объекта, точечный оператор использовать нельзя; необходимо использовать квадратные скобки. Поскольку после точечного оператора идёт строка, происходит обращение к строковому свойству sy, а не к свойству sy со значением Symbol.

let syObject = {}; syObject[sy] = "kk"; syObject[sy]; // "kk" syObject.sy; // undefined

На что обратить внимание

Когда значение Symbol используется в качестве имени свойства, это свойство является публичным, а не приватным, и доступно вне класса. Однако оно не появится в циклах for...in или for...of и не будет возвращено Object.keys() или Object.getOwnPropertyNames(). Чтобы прочитать Symbol-свойства объекта, их можно получить через Object.getOwnPropertySymbols() и Reflect.ownKeys().

let syObject = {}; syObject[sy] = "kk"; console.log(syObject); for (let i in syObject) { console.log(i); } //Нет вывода Object.keys(syObject); // [] Object.getOwnPropertySymbols(syObject); // [Symbol(key1)] Reflect.ownKeys(syObject); // [Symbol(key1)]

Определение констант

В ES5 строки используются для представления констант. Например:

const COLOR_RED = "red";
const COLOR_YELLOW = "yellow";
const COLOR_BLUE = "blue";

Но использование строк не гарантирует уникальность констант, что может вызвать некоторые проблемы:

const COLOR_RED = "red"; const COLOR_YELLOW = "yellow"; const COLOR_BLUE = "blue"; const MY_BLUE = "blue"; function ColorException(message) { this.message = message; this.name = "ColorException"; } function getConstantName(color) { switch (color) { case COLOR_RED : return "COLOR_RED"; case COLOR_YELLOW : return "COLOR_YELLOW "; case COLOR_BLUE: return "COLOR_BLUE"; case MY_BLUE: return "MY_BLUE"; default: throw new ColorException("Не удаётся найти этот цвет"); } } try { var color = "green"; //green выбрасывает исключение var colorName = getConstantName(color); } catch (e) { var colorName = "unknown"; console.log(e.message, e.name); //Передайте объект исключения в обработку ошибок }

Но использование Symbol для определения констант может гарантировать, что значения этой группы констант все различны. Используйте Symbol, чтобы изменить приведённый выше пример.

const COLOR_RED = Symbol("red"); const COLOR_YELLOW = Symbol("yellow"); const COLOR_BLUE = Symbol("blue"); function ColorException(message) { this.message = message; this.name = "ColorException"; } function getConstantName(color) { switch (color) { case COLOR_RED : return "COLOR_RED"; case COLOR_YELLOW : return "COLOR_YELLOW "; case COLOR_BLUE: return "COLOR_BLUE"; default: throw new ColorException("Не удаётся найти этот цвет"); } } try { var color = "green"; //green выбрасывает исключение var colorName = getConstantName(color); } catch (e) { var colorName = "unknown"; console.log(e.message, e.name); //Передайте объект исключения в обработку ошибок }

Значения Symbol уникальны, поэтому не будет констант с одинаковым значением, что гарантирует выполнение оператора switch так, как задумано в коде.

Symbol.for()

Symbol.for() похож на шаблон singleton. Сначала он выполняет глобальный поиск среди зарегистрированных Symbol, чтобы проверить, есть ли значение Symbol, у которого этот строковый параметр является именем. Если да, он возвращает это значение Symbol; если нет, он создаёт новое значение Symbol со строковым параметром в качестве имени, регистрирует его в глобальной среде для будущих поисков.

let yellow = Symbol("Yellow"); let yellow1 = Symbol.for("Yellow"); yellow === yellow1; // false let yellow2 = Symbol.for("Yellow"); yellow1 === yellow2; // true

Symbol.keyFor()

Symbol.keyFor() возвращает ключ зарегистрированного значения Symbol, который используется для проверки, было ли зарегистрировано значение Symbol с этим строковым параметром в качестве его имени.

let yellow1 = Symbol.for("Yellow"); Symbol.keyFor(yellow1); // "Yellow"