
Символи
Символите са нови примитивнитип, въведен в ES6. Символите са напълно уникални идентификатори. Подобно на техните примитивни аналози ( Number , String , Boolean ), те могат да бъдат създадени с помощта на фабричната функция, Symbol()
която връща символ.
const symbol = Symbol('description')
Всеки път, когато извикате фабричната функция, се създава нов и уникален символ. Незадължителният параметър със стойност на низ е описателен низ, който се показва при отпечатване на символа.
> symbol Symbol(description)
Всеки символ, върнат от, Symbol()
е уникален, така че всеки символ има своя собствена идентичност:
> Symbol() === Symbol() false
Можете да видите, че символите са примитивни, ако приложите typeof
оператора към един от тях - той ще върне нов резултат, специфичен за символа:
> typeof symbol 'symbol'
Случай на употреба: Символи като ключове на непублични свойства
Винаги, когато в JavaScript има йерархии за наследяване, имате два вида свойства (например създадени чрез класове, чисто прототипен подход):
- Публичните свойства се виждат от клиентите на кода
- Частните свойства се използват вътрешно в частите, които съставляват йерархията на наследяване (например класове, обекти).
За удобство, публичните свойства обикновено имат низови ключове. Но за частни имоти с низови ключове случайните сблъсъци на имена могат да се превърнат в проблем. Следователно символите са добър избор.
Например в следния код се използват символи за частни имоти _counter
и _action
:
const _counter = Symbol('counter'); const _action = Symbol('action'); class Countdown { constructor(counter, action) { this[_counter] = counter; this[_action] = action; } dec() { let counter = this[_counter]; if (counter < 1) return; counter--; this[_counter] = counter; if (counter === 0) { this[_action](); } } }
Имайте предвид, че символите ви предпазват само от сблъсъци с имена, а не от неоторизиран достъп. Можете да разберете всички ключове за свойства на обекта - включително символи - чрез следното:
const obj = { [Symbol('my_key')] : 1, enum : 2, nonEnum : 3 }; Object.defineProperty(obj, 'nonEnum', { enumerable: false }); // Making 'nonEnum' as not enumerable. // Ignores symbol-valued property keys: > Object.getOwnPropertyNames(obj) ['enum', 'nonEnum'] // Ignores string-valued property keys: > Object.getOwnPropertySymbols(obj) [Symbol(my_key)] // Considers all kinds of keys: > Reflect.ownKeys(obj) [Symbol(my_key),'enum', 'nonEnum'] // Only considers enumerable property keys that are strings: > Object.keys(obj) ['enum']
Наистина ли се нуждаем от символи?
Използвайте символи, когато вашето изискване е едно от следните:
- Enum: За да ви позволи да дефинирате константи със семантични имена и уникални стойности.
const directions = { UP : Symbol( ‘UP’ ), DOWN : Symbol( ‘DOWN’ ), LEFT : Symbol( ‘LEFT’ ), RIGHT: Symbol( ‘RIGHT’ ) };
- Сблъсъци на имена: когато искате да предотвратите сблъсъци с ключове в обекти
- Поверителност: когато не искате свойствата на обекта ви да бъдат изброени
- Протоколи: За да дефинирате как даден обект може да бъде повторен.
Представете си например библиотека като
dragula
дефиниране на протокол чрезSymbol.for(dragula.moves)
. Можете да добавите метод за товаSymbol
към всеки DOM елемент. Ако DOM елемент следва протокола, тогаваdragula
би могъл да извикаel[Symbol.for('dragula.moves')]()
дефинирания от потребителя метод, за да твърди дали елементът може да бъде преместен. - Добре известни символи: В допълнение към дефинираните от потребителя символи, JavaScript има и някои вградени символи. Те представляват вътрешно езиково поведение, което не е било изложено на разработчиците в <ES5. Повече информация тук .
Заключение
Symbols
в JavaScript може да осигури уникалност на нивото на достъп до обектите. Струва си всички разработчици да имат основно разбиране за тях и техните различни случаи на употреба.
code = coffee + developer