ОБНОВЛЕНИЕ : Недавно вышла блестящая статья от Mozilla . Прочитайте это, если вам интересно.
Как вы, возможно, знаете, они планируют включить новый тип примитива Symbol в ECMAScript 6 (не говоря уже о некоторых других сумасшедших вещах). Я всегда думал, что :symbol
понятие в Ruby не нужно; вместо этого мы могли бы легко использовать простые строки, как в JavaScript. И теперь они решили все усложнить в JS этим.
Я не понимаю мотивацию. Может ли кто-нибудь объяснить мне, действительно ли нам нужны символы в JavaScript?
private
иpublic
ключевыми словами атрибутов класса , что они решили канаву для более простой реализации класса. Вместоthis.x = x
вас должны были делатьpublic x = x
и частные переменныеprivate y = y
. Они решили отказаться от этого для гораздо более минимальной реализации класса. Тогда Symbol будет необходимым обходным путем для получения частных свойств в минимальной реализации.Ответы:
Первоначальной мотивацией для введения символов в Javascript было включение частных свойств.
К сожалению, они оказались серьезно понижены. Они больше не являются частными, так как вы можете найти их с помощью отражения, например, с помощью
Object.getOwnPropertySymbols
или прокси.Теперь они известны как уникальные символы, и их единственное предназначение - избежать столкновения имен между свойствами. Например, сам ECMAScript теперь может вводить хуки расширения с помощью определенных методов, которые вы можете наложить на объекты (например, для определения их протокола итерации), не рискуя столкнуть их с именами пользователей.
Независимо от того, что является достаточно сильным побуждением для добавления символов языка является дискуссионным.
источник
Object.getOwnPropertySymbols
не единственная утечка; более сложным является возможность использования прокси для перехвата доступа к «частному» свойству.Символы не гарантируют истинную конфиденциальность, но могут использоваться для разделения общих и внутренних свойств объектов. Давайте рассмотрим пример, в котором мы можем использовать
Symbol
частные свойства.Давайте рассмотрим пример, когда свойство объекта не является частным.
Выше
Pet
свойство классаtype
не является частным. Чтобы сделать это частным, мы должны создать закрытие. Приведенный ниже пример иллюстрирует, как мы можем сделатьtype
приватным использование замыкания.Недостаток вышеуказанного подхода: мы вводим дополнительное закрытие для каждого
Pet
созданного экземпляра, что может снизить производительность.Теперь мы представляем
Symbol
. Это может помочь нам сделать собственность частной, не используя лишних ненужных замыканий. Пример кода ниже:источник
_
не гарантирует истинную конфиденциальность, но может использоваться для разделения открытых и внутренних свойств объектов. Другими словами, бессмысленный ответ.Symbols
это новый, особый вид объекта, который можно использовать как уникальное имя свойства в объектах. ИспользованиеSymbol
вместоstring
позволяет различным модулям создавать свойства, которые не конфликтуют друг с другом.Symbols
также может быть закрытым, чтобы к его свойствам не мог получить доступ никто, кто еще не имеет прямого доступа кSymbol
.Symbols
новый примитив . Точно так же какnumber
,string
иboolean
примитивы,Symbol
есть функция , которая может быть использована для их создания. В отличие от других примитивов,Symbols
не имеют буквального синтаксиса (например, какstring
есть''
) - единственный способ создать их с помощьюSymbol
конструктора следующим образом:На самом деле,
Symbol
это просто немного другой способ прикрепления свойств к объекту - вы можете легко предоставить общеизвестныеSymbols
как стандартные методы, точно такие,Object.prototype.hasOwnProperty
которые появляются во всем, что наследуется отObject
.Вот некоторые из преимуществ
Symbol
примитивного типа.Symbols
иметь встроенную функцию отладкиSymbols
можно дать описание, которое на самом деле просто используется для отладки, чтобы немного облегчить жизнь при регистрации их на консоли.Symbols
можно использовать какObject
ключиЭто где
Symbol
действительно интересно. Они сильно переплетены с предметами.Symbol
можно назначать в качестве ключей для объектов, то есть вы можете назначить неограниченное количество уникальныхSymbol
объектов и гарантировать, что они никогда не будут конфликтовать сstring
ключами или другими уникальнымиSymbols
.Symbols
может использоваться как уникальное значение.Давайте предположим , что у вас есть библиотека протоколирования, которая включает в себя несколько уровней журналов , таких как
logger.levels.DEBUG
,logger.levels.INFO
,logger.levels.WARN
и так далее. В коде ES5 вы хотели бы сделать этиstring
s (такlogger.levels.DEBUG === 'debug'
) илиnumber
s (logger.levels.DEBUG === 10
). Оба из них не идеальны, так как эти значения не являются уникальными значениями, ноSymbol
есть! Такlogger.levels
просто становится:Узнайте больше в этой замечательной статье .
источник
log.levels = {DEBUG: Symbol('debug')
а не простоlog.levels = {DEBUG:'debug'}
. в конце это то же самое. Я думаю, что стоит упомянуть, что символы невидимы при переборе ключей объекта. это их "вещь"{}
и достичь того же результата (в качестве уникального значения), или, возможно, в этом проекте предпочтителен литерал, или вы можете сказать, что сначала нужно прочитать документ.) Я лично думаю, что это обеспечивает хорошую читабельность уникального значения в кодеSymbol("some message")
становится{message:'some message'}
, возможно, объект здесь лучше, так как вы можете добавить несколько полей.Этот пост о
Symbol()
, снабженный фактическими примерами, которые я мог найти / сделать, и фактами и определениями, которые я мог найти.TLDR;
Тип
Symbol()
данных, представленный в выпуске ECMAScript 6 (ES6).Есть два любопытных факта о Символе.
первый тип данных и единственный тип данных в JavaScript, который не имеет литерала
любая переменная, определенная с помощью
Symbol()
, получает уникальный контент, но на самом деле он не является частным .любые данные имеют свой собственный символ, и для тех же данных символы будут одинаковыми . Больше информации в следующем параграфе, иначе это не TLRD; :)
Как мне инициализировать символ?
1. Получить уникальный идентификатор с отладочным значением
Вы можете сделать это так:
Или так:
"some text here"
Строка не может быть извлечена из символа, это просто описание для целей отладки. Это никак не меняет поведение символа. Хотя, вы могли быconsole.log
это сделать (что справедливо, поскольку значение используется для отладки, чтобы не перепутать этот журнал с какой-либо другой записью журнала):2. Получить символ для некоторых строковых данных
В этом случае значение символа фактически учитывается, и таким образом два символа могут быть неуникальными.
Давайте назовем эти символы символами второго типа. Они никак не пересекаются с символами «первого типа» (т. Е. Теми, которые определены с помощью
Symbol(data)
).Следующие два абзаца относятся только к символу первого типа .
Как извлечь выгоду из использования Symbol вместо старых типов данных?
Давайте сначала рассмотрим объект, стандартный тип данных. Мы могли бы определить несколько пар ключ-значение и получить доступ к значениям, указав ключ.
Что если у нас есть два человека с именем Питер?
Делая это:
не имеет особого смысла.
Таким образом, возникает проблема двух абсолютно разных людей, имеющих одинаковые имена. Давайте тогда ссылаться на новое
Symbol()
. Это как человек в реальной жизни - любой человек уникален , но его имена могут быть одинаковыми. Давайте определим два «человека».Теперь у нас есть два разных человека с одинаковыми именами. Наши люди действительно разные? Они есть; Вы можете проверить это:
Какую пользу мы получаем там?
Мы можем сделать две записи в вашем объекте для разных людей, и они не могут быть ошибочно приняты.
Используя эту инициализацию, абсолютно невозможно перепутать записи для первого и второго лица. Вызов
console.log
для них правильно выведет их вторые имена.Когда он используется в объекте, чем он отличается от определения не перечислимого свойства?
Действительно, уже существовал способ определения свойства, от которого необходимо скрыть,
Object.keys
и перечисления. Вот:Какая разница
Symbol()
? Разница в том, что вы все еще можете получить свойство, определенноеObject.defineProperty
обычным способом:И если определено с символом, как в предыдущем абзаце:
У вас будет возможность получить его значение, только если вы знаете его переменную, т.е.
Более того, определение другого свойства под ключом
"apple"
приведет к тому, что объект отбросит более старое (и если его жестко закодировать, это может привести к ошибке). Так что, яблок больше нет! Какая жалость. Ссылаясь на предыдущий абзац, символы являются уникальными и определяют ключ,Symbol()
который сделает его уникальным.Преобразование типов и проверка
В отличие от других типов данных, невозможно преобразовать их
Symbol()
в любой другой тип данных.Можно «сделать» символ, основанный на примитивном типе данных, путем вызова
Symbol(data)
.С точки зрения проверки типа ничего не меняется.
источник
Вот как я это вижу. Символы обеспечивают «дополнительный уровень конфиденциальности», предотвращая раскрытие ключей / свойств объекта с помощью некоторых популярных методов, таких как Object.keys () и JSON.stringify ().
Несмотря на то, что объект задан как таковой, такие свойства все еще могут быть доступны через рефлексию, прокси, Object.getOwnPropertySymbols () и т. Д., Но нет естественных средств для доступа к ним через несколько прямых методов, которых иногда может быть достаточно с точки зрения ООП.
источник
Символ JS - это новый примитивный тип данных. Это токены, которые служат уникальными идентификаторами . Символ может быть создан с помощью
Symbol
конструктора. Взять, к примеру, этот фрагмент из MDN:Часто удобно использовать символы в качестве уникальных ключей свойств объекта, например:
источник
Источник
источник