всем холодно, я вернулся, к счастью, больше не болен, или может быть, может быть, я никогда не был болен, может быть, я две недели пытался отрастить усы, и они так плохо выглядят, что я не хотел быть на камере, поэтому я солгал и сказал, что болен, это возможно, но на самом деле я был болен, так что это видео о символах JavaScript, источнике путаницы среди моих студентов. Это видео довольно полное, но сразу скажу, что я не рассматриваю одну тему, связанную с символами, потому что я собираюсь сделать отдельное видео по этой теме, которое называется итераторы и известные символы. Так что есть так называемые известные символы, о которых я не говорю в этом видео, но остальное я рассмотрю. Что еще? О, поставьте лайк этому видео, подпишитесь на канал и включите уведомления. Последние несколько видео были сделаны по предложениям от подписчиков и людей, которые включили уведомления, поэтому, если вы хотите помочь определить, что будет дальше, подпишитесь, хорошо? Давайте начнем с символов. Хорошо, давайте начнем с самого простого вопроса: что такое символ? Символ - это новый примитивный тип в JavaScript, такой же, как число, строка и логическое значение. Теперь у нас есть новый член в этой группе, называемый символ. Возможно, вы задаетесь вопросом, что именно он представляет, что такое символ? Это просто уникальное значение, специальное значение, которое будет уникальным за кадром. Вы можете представить его как очень длинное число, которое будет оставаться уникальным каждый раз, когда вы создаете новый символ. Мы используем их в ситуациях, когда нам нужно иметь уникальное значение, обычно, когда мы пытаемся избежать конфликтов имен между переменными или, скорее всего, ключами свойств в объекте, но мы вернемся к этому. В отличие от этих примеров, здесь нет красивого синтаксиса для создания символа, как для создания строки. Обычно мы просто пишем символ, а не набираем его полностью. То же самое с числом, обычно мы просто пишем цифру 3, у нас есть такой сокращенный синтаксис, но с символом это невозможно, нет сокращенного синтаксиса. Если вы хотите создать новый символ, вы должны каждый раз писать это. Вы можете необязательно передать что-то внутрь, мы к этому вернемся, вы можете туда что-то поместить, но это не оказывает влияния на значение этого символа, это как метка, это помогает при отладке, чтобы понять, с чем должен соответствовать символ, но в конечном итоге это все, что вам нужно. Каждый раз, когда вы запускаете это, за кадром вы получаете специальное уникальное значение, все они будут разными, это не значит, что они выводятся по-разному, они выглядят одинаково, но за кадром они не одинаковые. Давайте докажем это просто, создадим переменную с именем sim1 и присвоим ей значение символа, а затем продублируем это и сделаем sim2. Эти два будут выглядеть одинаково, когда мы их выводим или возвращаем, но если мы проверим их на равенство, они совсем не одинаковы, мы получим false.




Так вспомните, что на самом деле за кадром можно представить огромные числа, и они гарантированно будут разными, за исключением одного нюанса, о котором я расскажу в конце этого видео. Есть ситуация, когда вы можете создавать символы, которые не будут уникальными, но чтобы показать вам это, это все равно работает, если мы передадим описатель, небольшую метку, например, если я создам два символа, в которых передам строку "cat", они не будут равны друг другу, они совершенно разные. Но все же хорошо передавать эти строки, потому что теперь, когда я смотрю на sim1, если я пытаюсь понять, что это за символ, он говорит мне, что это символ и в некотором роде соответствует "cat", но это не означает, что символ как-то основывается на строке "cat", он не использует ее никаким образом, кроме отладки и улучшения понимания. Хорошо, с этим разобрались, то о чем я хочу поговорить в основном в этом видео - почему вам нужны эти уникальные значения, зачем вам такое значение? Символы используются, в основном, как идентификаторы в свойствах объектов, согласно документации MDN, это их единственное назначение, это довольно прямолинейно. Допустим, у нас есть некоторые объекты-загадки, которые я здесь свернул, мы не знаем, что в них находится, скажем, они поступают из другого источника, мы получаем несколько разных объектов, и мы хотим добавить к каждому из них уникальный идентификатор, чтобы мы могли отслеживать их. Если я просто сделаю user.id = что-то вроде этого, это будет проблематично, потому что, о чудо, там уже есть идентификатор, кто бы мог подумать, и мы его полностью игнорируем, перезаписываем и его больше нет. Чтобы избежать этой ситуации, хотя это и выдумано, представьте, что есть множество реальных сценариев, где вам нужно добавить какое-то свойство и гарантировать, что оно не конфликтует с чем-то, вместо этого мы можем создать символ. Мы можем сказать, что I D symbol = symbol, передать необязательное описание, и затем мы просто добавляем его в качестве ключа и устанавливаем равным тому, как выглядит наш идентификатор, и теперь, если у нас есть пользователь, у нас все еще есть исходный идентификатор, а также этот символ идентификатора, и чтобы получить его, нам просто нужно использовать этот символ идентификатора, сохранить эту ссылку и сказать пользователь.идентификатор-символа, вот так, и мы получим этот идентификатор. Теперь, если мы хотим сделать это встроенным в объект литерал, и я хочу сказать I D symbol прямо здесь, вот так, это не сработает, на самом деле происходит следующее, у нас получается строка, если мы посмотрим на пользователя, он действительно добавляет идентификатор-символ, но он не понимает, что это символ.



Вот как выглядит дополнительный синтаксис: нам нужно добавить квадратные скобки вокруг этого, и теперь, если мы посмотрим на объект "user", вы увидите, что он снова стал символом. Изначально символы предполагали использование для создания приватных свойств в JavaScript, но это не сработало, и эту идею в основном отбросили. Однако важно отметить, что символы не отображаются в данном объекте. Если мы выполним "Object.getOwnPropertyNames(user)", передав в него символ "ID", его там не будет. Мы получим только свойства "ID", "name", "city" и "age". Если мы переберем свойства объекта с помощью цикла "for ... in", мы также не увидим этот символ. Но мы можем найти его, они не совсем скрыты, они не являются приватными. Мы можем использовать "Object.getOwnPropertySymbols", и они появятся. Просто передаем в него объект "user", и вот они. Я просто хочу прояснить это: символы не являются приватными и не скрыты навсегда, они просто неочевидны, допустим так сказать. Теперь, прежде чем я перейду к примерам использования и покажу вам немного более сложный код, хотя ничто не является очень сложным, если честно, я хочу упомянуть, что символы дают вам уникальные значения, но это не всегда так, есть одно исключение. Вы можете использовать метод "Symbol.for", который даст вам символ, но он не будет уникальным для данного описателя. Например, я могу сказать "Symbol.for('cat')" и каждый раз, когда я делаю "Symbol.for('cat')", давайте сделаем "const sim1 = Symbol.for('cat')" и продублируем это и сделаем "const sim2 = Symbol.for('cat')", они будут добавлены в так называемое глобальное пространство символов, и если мы посмотрим на них, они будут выглядеть одинаково, как всегда, но если мы выполним "sim1 === sim2", они будут эквивалентными. Когда мы используем "Symbol.for", это означает, что мы хотим глобальный символ, и идея состоит в том, что мы сможем ссылаться на символ "cat" позже, часто в другом окне, поэтому они общие для всех окон. Если вам нужно обмениваться или передавать символы, вот как это можно сделать. Но в остальных случаях, когда мы просто используем символы вот так


это совершенно разные вещи

уникальные значения, хорошо, давайте поговорим

о нескольких случаях использования. Вот один

пример, где мы используем символы для представления понятий,

идей, чего-то уникального. В этом

случае у нас есть функция с именем get

threat level, она принимает цвет и

возвращает строку, например, "сильный", "высокий",

"повышенный", в зависимости от цвета. Идея, я думаю, основана на

уровне угрозы терроризма, что-то в этом роде.

Так что мы передаем красный, и все они

все эти цвета в настоящее время являются строками,

что работает, за исключением того, что они не

уникальны. Так что что-то может произойти

возможно, моя кошка, ее имя совпадает

с синим. Я могу передать "кошка" и получить

уровень угрозы, и все равно получить "низкий",

что будет результатом, если мы передадим синий.

Теперь это может быть не такая большая проблема, но

мы можем сделать следующее: заменить все это

заменить все это символами, и теперь, если мы попытаемся

вызвать get threat level и передать синий, который

основан на символе, мы получим "низкий", но если я передам

мою кошку, которая является строкой "синий", мы больше не получим

этого. Это совершенно разные вещи, поэтому у нас есть

эти уникальные понятия, которые мы можем использовать. Хорошо, следующий пример предназначен для

показать, как вы можете использовать символы для

хранения метаданных на объекте. У меня есть класс с именем train

и он состоит из нескольких вагонов, например,

вагон-холодильник с крупным рогатым скотом, вагон-цистерна с молоком, вагон-шахтный с углем и так далее. И у меня есть длина, которая является своего рода метаданными, и сейчас она просто обычное свойство. Но когда я итерирую по нему и, скажем, просто печатаю все, оно печатает длину и для каждого вагона, по которому я итерирую, и если я не хочу, чтобы это происходило, я могу использовать символ, вот так. Я создаю символ, сохраняю его в переменную, а затем использую его в качестве ключа. Я начинаю с нуля и добавляю единицу к этому свойству, используя символ для доступа к нему, и теперь, когда я печатаю все, мы пропускаем его, потому что, помните, когда мы перебираем объект, символы на самом деле не включены, мы можем получить доступ к ним, но мы должны делать это вручную. Так что последние два примера немного специфичны, а этот третий, который я вам показываю, определенно самое распространенное применение, а именно использование символов в качестве ключей для предотвращения конфликтов или столкновений имен. Это основано на реальной вещи, очень упрощенной, но представьте, что мы работаем над веб-сайтом, у нас есть множество компонентов, не важно, какие они, но представьте себе кнопки, списки, формы, модальные окна и другие компоненты, и в любой момент может возникнуть проблема или проблема с одним из них, поэтому у нас есть служба предупреждений, чтобы управлять всеми этими предупреждениями и, в основном, отслеживать и удалять их при необходимости. Служба предупреждений - это просто объект с возможностью добавления и удаления предупреждений, и что важно, здесь, в моем компоненте, каждый раз, когда мы создаем новый компонент, он получает специальный идентификатор компонента, который является символом, так что у меня может быть два разных компонента списка, но они имеют совершенно разные, хотя они выглядят одинаково, но у них совершенно разные символы, разные идентификаторы, и таким образом, если оба из них имеют проблемы одновременно, оба они могут быть внутри нашей службы предупреждений без проблем. Если я вызову эту функцию обработки ошибок, все, что она делает, это берет этот идентификатор компонента и добавляет предупреждение в нашу службу предупреждений с использованием этого идентификатора с сообщением. Если мы посмотрим на эту службу предупреждений, она не очень захватывающая, но мы видим, что там есть два предупреждения, оба символа компонента списка, но они уникальны, поэтому, если это происходит динамически или, может быть, это анимации или мы работаем с кэшем и не знаем заранее, что там находится, это способ, которым мы можем использовать символы для создания этих уникальных идентификаторов, чтобы мы могли добавить что-то и не беспокоиться о перезаписи чего-либо, нет конфликта, нет угрозы перезаписи вещей. Хорошо, надеюсь, это понятно.


+ -> comment
галочка -> content