Кратко
СкопированоСимвол (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/bar/foo/baz""foobarfoobaz".split(new MySplit("bar")) // "bar/foo/bar/foobaz"
"foobarfoobaz".split(new MySplit("foo")) // "foo/bar/foo/baz"
"foobarfoobaz".split(new MySplit("bar")) // "bar/foo/bar/foobaz"
Что хотят проверить?
СкопированоЭтот вопрос проверяет умеете ли вы использовать символы. Хотя такие вопросы задают редко, из-за специфичности темы, умение пользоваться символами – полезный инструмент, который вам обязательно пригодится.