ES6 Понимание итератора, итеративного, генератора

Python внешний интерфейс JavaScript ECMAScript 6

image

Что такое итератор?

удовлетворитьпротокол итератораОбъект.
протокол итератора: объектnextМетод - это функция без аргументов, которая возвращает объект, который имеетdoneа такжеvalueДва свойства:

  • done(boolean):
    • если итератор прошел итерируемую последовательностьtrue. В настоящее времяvalueможет описывать возвращаемое значение этого итератора.
    • Если итератор может дать следующее значение в последовательности, тоfalse.这等效于连同doneСвойства также не указаны.
  • value: любое значение JavaScript, возвращаемое итератором.doneдляtrueможно опустить.

ES5 реализует простой итератор:

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 }"

Что такое итерируемый объект (Iterable)?

удовлетворитьИтерируемый протоколОбъект является итерируемым объектом.
Итерируемый протокол: объект[Symbol.iterator]value — это функция без параметров, которая возвращает итератор.

В ES6 все объекты коллекции (Array,Setа такжеMap)так же какString,argumentsОба являются итерируемыми объектами, и все они имеют итераторы по умолчанию.

Итерируемые объекты могут использоваться в следующих операторах:

for (let value of ['a', 'b', 'c']) {
  console.log(value);
}
// "a"
// "b"
// "c"
[...'abc'];   // ["a", "b", "c"]
console.log(...['a', 'b', 'c']);   // ["a", "b", "c"]
function* gen() {
  yield* ['a', 'b', 'c'];
}

gen().next(); // { value: "a", done: false }
let [a, b, c] = new Set(['a', 'b', 'c']);
a;   // 'a'

пониматьfor...ofцикл

for...ofПринимает Iterable или значение, которое может быть приведено/обернуто в Iterable (например, 'abc'). При обходе,for...ofполучит итерируемый объект[Symbol.iterator](), вызовите next() для итератора последовательно, пока итератор не вернет значение объекта.doneсобственностьtrueКогда обход заканчивается, значение не обрабатывается.

for...ofПример цикла:

var a = ["a","b","c","d","e"];

for (var val of a) {
    console.log( val );
}
// "a" "b" "c" "d" "e"

Например, преобразуется в общую петлю, эквивалентно вышеуказанномуfor...ofцикл:

var a = ["a","b","c","d","e"];

for (var val, ret, it = a[Symbol.iterator]();
    (ret = it.next()) && !ret.done;
) {
    val = ret.value;
    console.log( val );
}
// "a" "b" "c" "d" "e"

сделать итератор итерируемым

существуетчто такое итераторраздел, мы настраиваем простую функцию, которая генерирует итераторcreateIterator, но итератор, сгенерированный этой функцией, не реализует итерируемый протокол, поэтому его нельзя использовать вfor...ofИ т.д., используемые в грамматике. Это может быть достигнуто протоколом итерации для объекта, в[Symbol.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
            };
        },
        [Symbol.iterator]: function () { return this }
    };
}

var iterator = createIterator([1, 2, 3]);
console.log(...iterator)

Что такое генератор (генератор)?

генераторная функция

Генераторная функция (GeneratorFunction)способен вернутьГенератор (Генератор)Функция.生成器函数由放在 function 关键字之后的一个星号( * )来表示,并能使用新的 yield 关键字。

function *aGeneratorfunction(){
  yield 1
  yield 2
  yield 3
};

var aGeneratorObject = aGeneratorfunction()
// 生成器对象
aGeneratorObject.toString()   // "[object Generator]"

Объекты Builder являются как итераторы и итеративные объекты

function *aGeneratorfunction(){
  yield 1
  yield 2
  yield 3
};

var aGeneratorObject = aGeneratorfunction()

// 满足迭代器协议,是迭代器
aGeneratorObject.next()   // {value: 1, done: false}
aGeneratorObject.next()   // {value: 2, done: false}
aGeneratorObject.next()   // {value: 3, done: false}
aGeneratorObject.next()   // {value: undefined, done: true}

// [Symbol.iterator]是一个无参函数,该函数执行后返回生成器对象本身(是迭代器),所以是可迭代对象
aGeneratorObject[Symbol.iterator]() === aGeneratorObject   // true

// 可以被迭代
var aGeneratorObject1 = aGeneratorfunction()
[...aGeneratorObject1]   // [1, 2, 3]

Взамен Строитель

перебрать возвращаемый объектdoneзначениеtrueИтерация заканчивается, когдаvalueиметь дело с.

function *createIterator() {
  yield 1;
  return 42;
  yield 2;
}

let iterator = createIterator();
iterator.next();   // {value: 1, done: false}
iterator.next();   // {value: 42, done: true}
iterator.next();   // {value: undefined, done: true}

doneКогда значение истинно, итерация завершается, и итерация не обрабатывает значение. Таким образом, для этого обхода итератора значение 42 не будет обработано.

let iterator1 = createIterator();
console.log(...iterator);   // 1

Добавить к[Symbol.iterator]СделатьObjectповторяемый

согласно сИтерируемый протокол,ДатьObjectДобавлен прототип[Symbol.iterator]Нет возвращаемого значения - это эталонная функция объекта, объект возвращается соответствие протокола итератора.

Object.prototype[Symbol.iterator] = function () {
  var i = 0
  var items = Object.entries(this)
  return {
    next: function () {
      var done = (i >= items.length);
      var value = !done ? items[i++] : undefined;

      return {
          done: done,
          value: value
      };
    }
  }
}

var a = {
  name: 'Jimmy',
  age: 18,
  job: 'actor'
}

console.log(...a)   // [ 'name', 'Jimmy' ] [ 'age', 18 ] [ 'job', 'actor' ]

Упростите свой код с помощью генераторов:

Object.prototype[Symbol.iterator] = function* () {
  for (const key in this) {
    if (this.hasOwnProperty(key)) {
      yield [key, this[key]];
    }
  }
}

var a = {
  name: 'Jimmy',
  age: 18,
  job: 'actor'
}

console.log(...a)   // [ 'name', 'Jimmy' ] [ 'age', 18 ] [ 'job', 'actor' ]

делегат генератораyield*

function* g1() {
  yield 1;
  yield 2;
}

function* g2() {
  yield* g1();
  yield* [3, 4];
  yield* "56";
  yield* arguments;
}

var generator = g2(7, 8);
console.log(...generator);   // 1 2 3 4 "5" "6" 7 8

последний пример

Проанализируйте следующий код:

function* fibs() {
  var a = 0;
  var b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(first, second, third, fourth, fifth, sixth);

В этом кодеfibsгенератор, генерирующий бесконечно длинные последовательности Фибоначчи,[a, b] = [b, a + b]Это назначение обмена назначения реструктуризации (= присвоение рассчитывается справа налево, поэтому сначала вычислите правую сторону.a+b, а затем структура, каждая из которых имеет эффект назначения обмена), написанная на ES5 для создания массива конечной длины следующим образом:

function fibs1(n) {
  var a = 0;
  var b = 1;
  var c = 0;
  var result = []
  for (var i = 0; i < n; i++) {
    result.push(a);
    c = a;
    a = b;
    b = c + b;
  }

  return result;
}

console.log(fibs1(6))   // [0, 1, 1, 2, 3, 5]

И в первом фрагменте кода изfibs()Первые шесть значений деконструируются из итератора (генератор — это подмножество итератора), пример кода следующий:

function* fibs2(n) {
  var a = 0;
  var b = 1;
  for (var i = 0; i < n; i++) {
    yield a;
    [a, b] = [b, a + b];
  }
}

console.log(...fibs2(6))

Зачем использовать итераторы, генераторы и каковы преимущества?

...пока не разобрался

Выше есть много частей, которые я понимаю лично, добро пожаловать на исправление ошибок (* ̄︶ ̄)

Ссылаться на: