[Внешний разговор_1] От для до Генератора

внешний интерфейс JavaScript ECMAScript 6
[Внешний разговор_1] От для до Генератора

чатfor of

Говоря оfor ofПоверьте, что все написалиJavaScriptлюди использовалиfor of, Для чего мы обычно его используем? В большинстве случаев это должен быть обход массива.Конечно, чаще мы также будем использоватьmap()илиfiler()для перебора массива. Но, как мы сказали в заголовке, это то же самое, что иGeneratorС чем это может быть связано?

Сначала мы думаем над вопросом, зачем использоватьfor ofилиmap()/filer()метод для перебора массива (или массивоподобного объекта:Strings , Maps , Sets , arguments) Шерстяная ткань? Почему их нельзя использовать для перебора объекта?

чему ты можешь научиться

  • правильноfor ofболее глубокое понимание
  • iteratorГде свято?
  • Массивы тоже объекты, почему их нельзя использовать?for ofперебирать объекты?
  • как реализовать объектfor of?
  • GeneratorГде свято? Чем он хорош?

Тайна массивоподобных объектов

Прежде чем откроется настоящая тайна, встаньтеfor ofПодумайте об этом с точки зрения, теперь позвольте вам пройтись по массиву, какую информацию вам нужно знать?

  • значение, соответствующее индексу
  • завершать ли обход

Имея это в виду, давайте напечатаем массив, чтобы увидеть загадку:

const numbersArray = [1, 2, 3];

console.dir(numbersArray);

Массивы (или массивоподобные объекты:Strings , Maps , Sets , arguments) реализует метод в прототипеSymbol.iterator, вопрос, то этоSymbol.iteratorКакая польза? Возьми и попробуй:

let iterator = numbersArray[Symbol.iterator]();
// 我们把这个 Symbol.iterator 打印一下看看里面到底有些什么
console.dir(iterator);

вот одинnext()Это правильный путь? выполнить этоnext()метод:

iterator.next(); // 输出 {value: 1, done: false}
iterator.next(); // 输出 {value: 2, done: false}
iterator.next(); // 输出 {value: 3, done: false}
iterator.next(); // 输出 {value: undefined, done: true}

Обратите внимание, что когда нижний индекс превышает значение: undefined

мы нашли этоiterator.next()Каждый раз возвращается объект. Этот объект содержит две части информации: значение текущего индекса и флаг, указывающий, завершен ли обход. Это подтверждает то, что мы думали раньше, с этими двумя частями информации вы, какfor ofфункция, также может распечатать каждый элемент массива, верно?

А вот и новый вопросiteratorГде свято?

iterator(итератор) &The iterator protocol(итеративный протокол)

болталиiteratorмы должны сказатьThe iterator protocol(итеративный протокол)

" The iterable protocol allows JavaScript objects to define or customize their iteration behavior " - MDN

Об этом говорится в MDN:The iterator protocolразрешатьJavaScriptобъектов, чтобы определить или настроить их поведение при итерации, поэтому приведенное вышеSymbol.iteratorЭтот метод является реализацией массива для данного протокола. Итак, согласно этому протоколу, как массив реализуетiteratorШерстяная ткань?

"In JavaScript an iterator is an object which defines a sequence and potentially a return value upon its termination. More specifically an iterator is any object which implements the Iterator protocol by having a next() method which returns an object with two properties: value, the next value in the sequence; and done, which is true if the last value in the sequence has already been consumed. If value is present alongside done, it is the iterator's return value." - MDN

Этот большой раздел кажется трудоемким.Короче говоря, как мы подтвердили в предыдущей главе, способ его реализации заключается в определенииnext()метод, и этоnext()Метод возвращает объект каждый раз, когда он выполняется:{value:xxx/undefined , done: true/false }вvalueпредставляет текущее пройденное значение,doneУказывает, завершен ли обход.

Этот раздел отвечает на наш предыдущий вопрос: почему бы не использоватьfor ofперебирать объект? причина проста:JavaScriptОбъект не реализует такойiterator. Вы можете распечатать объект, чтобы посмотреть, что из этого выйдет:

console.dir({ a: 1, b: 2 });

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

Почему нет встроенной итерации объекта? (почему вobjectКак насчет отсутствия встроенных итераторов?)

почему вobjectКак насчет отсутствия встроенных итераторов?

Да, почему? Нам также нужно обойти объект в различных сценариях? Почему нет встроенного итератора? Чтобы ответить на этот вопрос, мы должны взглянуть на некоторые основные понятия с другой точки зрения:

Мы часто говорим об обходе объектов, но, говоря простым языком, есть только два уровня для работы с одним.JavaScriptОбъект для обхода:

  • Иерархия программ - что это значит? На уровне программы, когда мы перебираем объект, мы перебираем свойства объекта, отображающие его структуру. Это может быть неправильно понято, например:Array.prototype.lengthЭто свойство связано со структурой объекта, но не с его данными.

  • Иерархия данных - означает повторение структуры данных и извлечение ее данных. Например: когда мы перебираем массив, итератор перебирает все его данные, еслиarray = [a, b, c, d]Затем итератор получает доступ1, 2, 3, 4.

понять причину,JavaScriptХотя не поддерживаетсяfor ofперебирать объекты, но предоставлятьfor inметод для перебора всех не-Symboltype и является перечислимым свойством.

Стандарт не поддерживает, если мы будем использоватьfor-ofперебирать объекты? Тогда мы можем произвольно реализовать один:

Object.prototype[Symbol.iterator] = function*() {
  for (const [key, value] of Object.entries(this)) {
    yield { key, value };
  }
};
for (const { key, value } of { a: 1, b: 2, c: 3 }) {
  console.log(key, value);
}

Не знаю, обратили ли вы внимание на какую-то деталь в нашем сознательном осуществленииiteratorВ коде мы используем очень странную структуруfunction*() {}, это то, что мы представим дальшеGenerator

Generators

Когда я вижу это имя, я думаю, что оно потрясающее, но на самом деле оно очень простое, просто напишитеGeneratorВам просто нужно добавить имя функции иfunctionДобавьте ключевое слово в середине*номера достаточно. Что касается внутриyieldЧто это такое, мы поговорим об этом позже.

talk is cheap , show me the code, На примере кратко расскажу о концепции.

Теперь мы определим такойGeneratorназываетсяgen

function* gen() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
}

Мы видим только, что в нем 4 утверждения, поэтому распечатайте его и посмотрите:

Знакомая функция была найдена здесь,next()метод, мы ставимgenсоздать его, выполнить егоnext()Посмотрим на результат:

Это все еще знакомый вкус, так что здесь мы уже знаем,Generatorможет создать экземплярiterator, и этоyieldОператоры используются для прерывания выполнения кода, то есть для взаимодействия сnext()метод, который будет выполняться только по одномуyieldутверждение.

Еще одно слово дляGeneratorСама по себе есть интересная особенность,yieldможет следовать за другимGeneratorи они будут выполняться в порядке:

function* gen() {
  yield 1;
  yield* gen2();
  return;
}

function* gen2() {
  yield 4;
  yield 5;
}

let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

Результаты интересные, не так ли? а такжеreturnзакончится весьGenerator, другими словами: напишите вreturnНазадyieldне будет выполняться.

Генератор для чего?

GeneratorВ чем польза?Умные студенты могли догадаться, да, это может прерывать функцию выполнения кода, что может помочь нам контролировать порядок выполнения асинхронного кода:

Например, есть две асинхронные функцииAа такжеB, а такжеBПараметрыAвозвращаемое значение , то есть, еслиAВыполнение не заканчивается, мы не можем выполнитьB.

Затем пишем псевдокод:

function* effect() {
  const { param } = yield A();
  const { result } = yield B(param);
  console.table(result);
}

В это время, если нам нужно получитьresultТогда нам нужно:

const iterator = effect()
iterator.next()
iterator.next()

сделать это дваждыnext()Получите результат, выглядит глупо, не так ли? Есть ли хороший способ? (ерунда, должно быть) Предположим, вы бежитеA() / B()После завершения запроса он будет выполнен автоматическиnext()метод? Разве это не решает?

Такая библиотека уже существовала, и вам рекомендуется обратиться к нейcoКонечно, вы также можете прочитать исходный кодэта статьяПриходите посмотреть, в конце концовGeneratorкак играть.

наконец

буклетХитрости отладки Chrome, о которых вы не зналиПредпродажа стартовала.

Добро пожаловать в публичный аккаунт "Front-end Bully", отсканируйте код, чтобы следовать, вас ждет много хорошего~