Интервью: Знаете ли вы, почему существует Генератор

интервью внешний интерфейс ECMAScript 6
Интервью: Знаете ли вы, почему существует Генератор

提示: Эта статья находится на github«Понимание ECMAScript 6»Заметки организованы, и примеры кода также получены из этого. Вы можете прочитать эту книгу непосредственно, когда у вас есть время. Несмотря на то, что он на английском языке, он прост для понимания и настоятельно рекомендуется.

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

原文链接

В основном представлено здесьgeneratorПроисхождение и некоторые основные понятия, которые вы поняли или хотите знатьgeneratorДля продвинутого использования вы можете прочитать этоКак сбросить ошибку в Генератор?

проблема с петлей

ES5Для итерации по массиву требуется следующее:

const colors = ["red", "green", "blue"];
for (var i = 0, len = colors.length; i < len; i++) {
  console.log(colors[i]);
}

Как можно видеть:

  1. Он должен отслеживать позицию нижнего индекса,
  2. Также определите, когда цикл остановится.

Логика этого кода проста, но написание сложное и скучное. И он очень часто используется, поэтому легко получить ошибки из-за дрожания рук. Для того, чтобы упростить написание и уменьшить вероятность ошибок,ES6Введены некоторые новые синтаксисы, один из которыхiterator.

что такое итератор

iteratorТоже объект, но с интерфейсом, рассчитанным на итерацию. она имеетnextметод, который возвращаетvalueиdoneобъект с двумя свойствами (далее именуемыйresult). Первое — это значение итерации, второе — флаг, указывающий, завершена ли итерация — логическое значение:trueУказывает, что итерация завершена,falseУказывает нет.iteratorВнутри есть указатель на позицию итерации, каждый вызовnext, автоматически перемещать указатель и возвращать соответствующийresult.

Ниже приведен обычайiterator:

function createIterator(items) {
  var i = 0;
  return {
    next: function () {
      var done = (i >= items.length);
      var value = !done ? items[i++] : undefined; return {
        done: done,
        value: value
      };
    }
  };
}



var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next());  // "{ value: 2, done: false }"
console.log(iterator.next());  // "{ value: 3, done: false }"
console.log(iterator.next());  // "{ value: undefined, done: true }"
// 后续的所有调用返回的结果都一样
console.log(iterator.next());  // "{ value: undefined, done: true }"

Видно, что нам нужно только продолжать выполнятьnextВсе, не нужно вручную отслеживать положение итерации. Проще, чем цикл в начале.

Уведомление:Возвращено последней итерациейvalueНе коллекция (в приведенном выше примере)items), ноundedinedИли возвращаемое значение функции.Проверьте здесь, чтобы понять взаимосвязь между возвращаемым значением и результатом

что такое генератор

Хотя приведенное вышеforЦикл проще, но вручную напишитеiteratorслишком много хлопот, так чтоES6посадочная дистанцияgenerator, легко создатьiterator. Это,generatorявляется возвращаемым значениемiteratorФункция.

Его синтаксис следующий:

function* createIterator() {
  yield 1;
  yield 2;
  yield 3;
}
// generators可以像正常函数一样被调用,不同的是会返回一个 iterator
let iterator = createIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3

Пример ясен,*указать, что этоgenerators,yieldпривык звонитьnextвернуться, когдаvalue.

в методеgenerator, можно сократить как:

let o = {
  createIterator: function* (items) {
    for (let i = 0; i < items.length; i++) {
      yield items[i];
    }
  }
};


// 等同于
let o = {
  *createIterator(items) {
    for (let i = 0; i < items.length; i++) {
      yield items[i];
    }
  }
};

можно увидеть, создатьgeneratorФункция имеет три метода

  1. объявление функции

    function* createIterator() {...}
    
  2. функциональное выражение

    const createIterator = function* () {...}
    
  3. сокращение в объекте

    let o = {
      *createIterator(items) {
         ...
       }
    };
    

Можно считать, что он находится в ключевом слове functionfunctionи имя функции с*, но имена клавиш и функций могут быть опущены в разных сценариях

[function] * [name]() {}

// * 可以靠近关键字也可以靠近函数名,或两不靠近,都可以

будь осторожен:

  1. должны знать о том,yieldНе может охватывать функции:

    function* createIterator(items) {
      items.forEach(function (item) {
        // 语法错误
        yield item + 1;
      });
    }
    
  2. Стрелочные функции нельзя использовать какgenerator

итерируемые циклы и циклы for-of

iterable

иiteratorтесно связаны, существуетiterableОбъект. она имеетSymbol.iteratorимущество, стоимость которогоgeneratorфункция.

Описано в коде,iterableЭто выглядит так:

let collection = {
  items: [],
  *[Symbol.iterator]() {
    for (let item of this.items) {
      yield item;
    }
  }
};

ES6Коллекции, такие как массивы, наборы, карты и даже строки вiterable.generatorСозданныйiteratorОн добавляется по умолчанию.Symbol.iterator, так они тожеiterable.

всеiterable, вы также можете использоватьfor-ofцикл.

цикл for-of

Хотя естьiterator, просто назовите егоnextметод, вы можете повторить. Однако вызывать каждый раз вручную слишком обременительно, поэтомуES6выпускfor-ofцикл:

const colors = ["red", "green", "blue"];
for (let color of colors) {
  console.log(color);
}

по сравнению с открытиемforцикл:

const colors = ["red", "green", "blue"];
for (var i = 0, len = colors.length; i < len; i++) {
  console.log(colors[i]);
}

Как можно видеть,for-ofцикл

  1. Нет необходимости отслеживать позицию итерации;
  2. Нет необходимости оценивать условие завершения цикла;

Просто объявите значение переменной activity для каждой итерации, лаконично и ясно.

Уведомление:for-ofможно использовать только вiterable, при использовании других объектов будет сообщено об ошибке.

встроенный итератор

iteratorдаES6Важная часть этого, некоторые встроенные типы данных встроеныiterator, что удобно для разработки.

Вот краткое введениеiteratorтип данных. Просто, но не маловажно.

итератор коллекции

ES6Существует три типа коллекций:

  1. множество
  2. set
  3. map

под нимиiteratorимеют:

entries():Возвращает итерируемый результат в виде пары ключ-значениеiterator; values():Возвращает итерируемый результат как значение в коллекцииiterator; keys():Возвращает результат итерации в виде набораkeyизiterator;

Ниже сmapНапример:

let tracking = new Map([
  ['name', 'jeyvie'],
  ['pro', 'fd'],
  ['hobby', 'programming']
]);

for (let entry of tracking.entries()) {
  console.log(entry);
}
// ["name", "jeyvie"]
// ["pro", "fd"]
// ["hobby", "programming"]

for (let key of tracking.keys()) {
  console.log(key);
}
// name
// pro
// hobby

for (let value of tracking.values()) {
  console.log(value);
}
// jeyvie
// fd
// programming

вsetвнутреннийkeyиvalueравны, обаsetзначение в . массивkeyэто его нижний индексindex, valueэто значение внутри.

Кроме того, каждая коллекция имеет по умолчаниюiteratorзаfor-ofперечислить. Результат его выполнения отражает то, как инициализируется коллекция.

пример вышеtracking:

for (let value of tracking) {
  console.log(value);
}
// ["name", "jeyvie"]
// ["pro", "fd"]
// ["hobby", "programming"]

соответствует этомуMapЭкземпляр — это дочерний элемент in и out — массив с двумя элементами.

другиеset, массивы похожи, поэтому не буду вдаваться в подробности.

нужно внимание, провереноchrome v65иnode v8.0Нет массивовvalues(). Может быть, потому что это избыточно для массивов.

итератор строк

в строкеiterator, вы можете понять предложение:основан наcode pointвместоcode unitповторяющийся. Сравните два примера:

例子1:на основеcode unit

var message = "A 𠮷 B";
for (let i=0; i < message.length; i++) {
    console.log(message[i]);
}

// A
// (空)
// � 
// � 
// (空)
// B

例子2:на основеcode point

var message = "A 𠮷 B";
for (let c of message) {
  console.log(c);
}

// A
// (空)
// 𠮷 
// (空)
// B

на основеcode pointМожет пониматься как основанный на символах, см. главу о строках, чтобы узнать, что это такое.

итератор для NodeList

повторить передNodeList(набор элементов), вам нужно использоватьforцикл:

// 可以这样
for (var i=0, len=NodeList; i<len; i++) {
	var el = NodeList[i]
	// ....
}

ES6Вы можете сделать это напрямую:

for (let el of NodeList) {
	// el 就是集合里的每个元素
}

Кроме того, сейчасNodeListТакже естьforEachметод

спред оператор

спред оператор...и повторяемый

Оператор спреда можно использовать на всехiterableна, и в соответствии сiterableпо умолчаниюiteratorРешите, какое значение взять.

Например, мы можем преобразовать строку в массив:

[...'A𠮷B']
// ['A', '𠮷', 'B']

Эпилог

здесь сforПроблема петли начинается, рассказываяES6как решить эту проблему, которая приводит кgenerator, а потом вывелiteratorиiterable, а операцияiterableизfor-of. Наконец сказалES6комбинированныйfor-of, может сделать内置集合операция удобнее.

Конечно,forПроблема с зацикливанием может быть не первойgeneratorПричины,generatorне просто решитьforРаспространите этот один вопрос, у него есть еще многоРасширенные возможности, имеет большую роль на практике, и я продолжу публиковать его позже.

Тогда почему я написал эту статью и стал "титульным участником"? Поскольку мне любопытно, я не просто хочу знать, как технология используется в настоящее время, но почему она существует и как она появилась. Таким образом, с одной стороны, мы можем лучше понять технологию, а с другой стороны, мы также можем лучше понять тенденцию технологического развития, Таким образом, мы можем ясно видеть фронт, и мы не будем спешить. и сделать так много обходных путей.

В конце концов, все это просто трюк, и каждый может критиковать и исправлять!

Кроме того,generatorРасширенное использованиеКак сбросить ошибку в Генератор?Написано, поправляйте.