Комментарии 14
На самом деле, до появления типа данных symbol сделать этого было нельзя.
На самом деле можно:
Object.defineProperty(myObject, 'newProperty', { value: ..., enumerable: false});
Символы и генераторы активно использовал в начале, но перестал. Единственное практическое применение для символов, что я нашел, это хранение метадаты, что нужно не часто. Для других целей, замусоривает код, а какой то однозначной пользы особо нет.
Генераторы, код слишком тяжело читать и соответственно поддерживать. Так же, для теории, я бы упомянул о yield* который позволяет «распаковывать» генератор внутри генератора, но использовать его я бы не рекомендовал, это усложняет код еще больше.
async/await тут вряд ли кто то будет спорить — гениальная вещь. Не хватает встроенной возможности отменять уже запущенные асинхронные операции, надеюсь это когда то добавят (или уже?).
Еще генераторы применяются вместо async/await в тех случаях когда стандартного поведения не достаточно и нужно выполнять дополнительную инициализацию перед началом выполнения каждого асинхронного продолжения.
Раздельная многозадачность, конечные автоматы и пр. это скорее какое-то специфическое применение генераторов. Стандартное — просто итерирования коллекций. Например, если вы работали с jQuery, то вот: for(const $node of $results) ;
, где в $.fn[Symbol.iterator]
задан нужный метод (удобнее использовать генераторы из-за сахара), который будет лениво обрамлять каждый под-элемент $()
-обёрткой.
Довольно много проектов, особенно backend, завязаны на различные трансформации одних цепочек данных в другие, самыми причудливыми способами. И там бывают самые причудливые коллекции. Да те же stream-ы из nodejs, к примеру, и те можно как-нибудь заитерировать (for await of
).
Т.е. в основе лежит вопрос не "зачем нужны генераторы", а вопрос "зачем нужен универсальный протокол итерирования", да ещё и ленивый. Ответив на него — легко ответить на первый вопрос — генераторы это сахар для итераторов.
Ну а так как генераторы потянули за собой существенные изменения в самом JS, то им нашли и разные нестандартные применения. Особенно лихой — замена async/await. Да и redux-saga отличились.
В ES2015 появился новый, шестой тип данных — symbol.
Лучше перефразировать в "… новый, шестой примитивный тип данных...", потому что по факту он не шестой, а седьмой.
Причина №2. Символы уникальныЭта «причина», мне кажется, показывает глубокое индусских разработчиков понимание различия между именем свойства и его значением.
Что, скажите, поменяется, если вместо
var includes = Symbol('will store custom includes method');
написать
var includes = 'will store custom includes method';
??
Да почти ничего:
...
//А здесь мы вызываем наш собственный метод includes
arr[includes](); // 'inside includes func', так как includes - это с̶и̶м̶в̶о̶л̵ строка
Поможет сделать строки уникальными, разве что, добавление случайного числа или глобального автоинкрементного счетчика — но, как по мне, больно некрасивый костыль получается. Для полифилов сойдет, но для написания нормальных библиотек символы лучше.
Поэтому можно говорить о том, что поведение Symbol.for напоминает шаблон проектирования синглтон.
По-моему, все-таки тут фабричный метод. Так как при разных значениях аргумента for мы получим разные значения, а синглтон всегда один
Отличная статья!
Символы, генераторы, async/await и асинхронные итераторы в JavaScript: их сущность, взаимосвязь и варианты использования