Кратко
СкопированоСимвол (Symbol
) — примитивный тип, значения которого создаются с помощью вызова функции Symbol
. Каждый созданный символ уникален.
Символы могут использоваться в качестве имён свойств в объектах. Символьные свойства могут быть прочитаны только при прямом обращении и не видны при обычных операциях.
Как пишется
СкопированоСоздание
СкопированоДля создания символа нужно вызвать функцию Symbol
:
const sym = Symbol()const symTwo = Symbol()console.log(sym === symTwo)// false
const sym = Symbol() const symTwo = Symbol() console.log(sym === symTwo) // false
При создании символа первым аргументом можно передать его описание. Оно ни на что не влияет и необходимо только для отладки. Даже если описания символов совпадают, JavaScript всё равно создаёт уникальные символы:
const sym = Symbol('name')const symTwo = Symbol('name')console.log(sym === symTwo)// false
const sym = Symbol('name') const symTwo = Symbol('name') console.log(sym === symTwo) // false
Использование
СкопированоСимволы используются для создания скрытых свойств объектов. В отличие от свойств, ключом которых является строка, символьные свойства может читать только владелец символа. Скрытые свойства не видны при его обходе с помощью for
:
const secondaryId = Symbol()const user = { 'id': 193, 'name': 'Ольга', [secondaryId]: 'olga-1'}for (const prop in user) { console.log(prop, user[prop])}// id 193// name Ольгаconsole.log(user[secondaryId])// olga-1
const secondaryId = Symbol() const user = { 'id': 193, 'name': 'Ольга', [secondaryId]: 'olga-1' } for (const prop in user) { console.log(prop, user[prop]) } // id 193 // name Ольга console.log(user[secondaryId]) // olga-1
Это может пригодиться, когда необходимо добавить свойства объекту, который могут модифицировать другие части программы. Таким образом только вы сможете читать созданное свойство, а гарантия уникальности символов гарантирует и отсутствие конфликтов имён.
Системные символы
СкопированоСимволы активно используются внутри самого JavaScript, чтобы определять поведение объектов. Такие символы называются «хорошо известными» (well-known symbols).
Самый известный символ Symbol
, который позволяет реализовать обход конструкции с помощью синтаксических конструкций for
и спред-синтаксиса.
Полный список таких символов доступен в спецификации, но на практике он нужен нечасто.
Глобальный реестр символов
СкопированоСозданный символ уникален, но как быть, если он нужен в нескольких местах программы? Для решения этой проблемы существует глобальный реестр символов, он хранит символы по строковым ключам. При обращении по ключу всегда будет возвращаться один и тот же символ.
Работа с реестром символов организована с помощью двух методов:
Symbol
— возвращает символ, хранящийся по ключу. Если символа ещё не существует, он создаётся автоматически.. for ( ключ ) Symbol
— возвращает строковый ключ, который хранит переданный символ или. keyFor ( символ ) undefined
, если символ не хранится в реестре.
const secondaryId = Symbol()const user = { 'id': 193, 'name': 'Ольга', [secondaryId]: 'olga-1'}console.log(Symbol.keyFor(secondaryId))// undefinedconst newSym = Symbol.for('registryKey')const newestSym = Symbol.for('registryKey')console.log(newSym === newestSym)// trueuser[newSym] = 'hello'console.log(Symbol.keyFor(newSym))// registryKey
const secondaryId = Symbol() const user = { 'id': 193, 'name': 'Ольга', [secondaryId]: 'olga-1' } console.log(Symbol.keyFor(secondaryId)) // undefined const newSym = Symbol.for('registryKey') const newestSym = Symbol.for('registryKey') console.log(newSym === newestSym) // true user[newSym] = 'hello' console.log(Symbol.keyFor(newSym)) // registryKey
На собеседовании
Скопировано отвечает
СкопированоЧто такое стратегия?
СкопированоСтратегия (Strategy) — это ООП поведенческий шаблон проектирования, который позволяет расширять базовый класс или метод новым функционалом. Для этого нужно передать в него, так называемый, конкретный класс. Например:
const Clock = new Clock // Создаем базовую версию часовconst GoldenClock = new Clock(new GoldenParts) // Часы с золотым оформлениемconst WoodenClock = new Clock(new WoodenParts) // Часы с деревянным оформлениемClock.draw() // Рисуем стандартную версию часовGoldenClock.draw() // Метод тот же, что и строкой выше, но теперь мы используем золотое оформлениеWoodenClock.draw() // Используем деревянное оформление
const Clock = new Clock // Создаем базовую версию часов const GoldenClock = new Clock(new GoldenParts) // Часы с золотым оформлением const WoodenClock = new Clock(new WoodenParts) // Часы с деревянным оформлением Clock.draw() // Рисуем стандартную версию часов GoldenClock.draw() // Метод тот же, что и строкой выше, но теперь мы используем золотое оформление WoodenClock.draw() // Используем деревянное оформление
Выполнение задачи
СкопированоЧтобы написать такой класс нам понадобится специальный well-known символ [
. Метод split
вызывает функцию [
, а результат вызова возвращает как результат split
. У строк это уже реализовано:
"123,4,56".split(",") // ["123", "4", "56]
"123,4,56".split(",") // ["123", "4", "56]
Мы можем добавить такое же поведение к своему классу:
class MySplit { constructor(value) { this.value = value; // Принимаем строку по которой будем сплитить } [Symbol.split](string) { // принимаем строку-аргумент (которую будем сплитить) // В конце необходимо вернуть полученный результат, иначе split() вернет undefined }}
class MySplit { constructor(value) { this.value = value; // Принимаем строку по которой будем сплитить } [Symbol.split](string) { // принимаем строку-аргумент (которую будем сплитить) // В конце необходимо вернуть полученный результат, иначе split() вернет undefined } }
Для нашей задачи разобьём строку при помощи регулярного выражения:
[Symbol.split](string) { // Заменяем все вхождения this.value на /${this.value}/ let index = string.replace(new RegExp(this.value, "g"), `/${this.value}/`); // убираем первый слэш, /url/Path -> url/Path if (index[0] === "/") index = index.substr(1) // Строка должна начинаться с url/, даже если его не было в начале if (!index.startsWith(this.value)) index = `${this.value}/` + index; return index;}
[Symbol.split](string) { // Заменяем все вхождения this.value на /${this.value}/ let index = string.replace(new RegExp(this.value, "g"), `/${this.value}/`); // убираем первый слэш, /url/Path -> url/Path if (index[0] === "/") index = index.substr(1) // Строка должна начинаться с url/, даже если его не было в начале if (!index.startsWith(this.value)) index = `${this.value}/` + index; return index; }
Пример работы
Скопировано"foobarfoobaz".split(new MySplit("foo")) // "foo/var/foo/baz""foobarfoobaz".split(new MySplit("bar")) // "bar/foo/bar/foobaz"
"foobarfoobaz".split(new MySplit("foo")) // "foo/var/foo/baz" "foobarfoobaz".split(new MySplit("bar")) // "bar/foo/bar/foobaz"
Что хотят проверить?
СкопированоЭтот вопрос проверяет умеете ли вы использовать символы. Хотя такие вопросы задают редко, из-за специфичности темы, умение пользоваться символами – полезный инструмент, который вам обязательно пригодится.