Heim  >  Artikel  >  Web-Frontend  >  Einführung in Iteratoren und Generatoren in JavaScript ES6

Einführung in Iteratoren und Generatoren in JavaScript ES6

巴扎黑
巴扎黑Original
2017-08-21 09:44:201088Durchsuche

Dieser Artikel führt hauptsächlich in ein tiefgreifendes Verständnis der ES6-Iteratoren und -Generatoren ein. Der Herausgeber findet ihn recht gut, daher werde ich ihn jetzt mit Ihnen teilen und als Referenz verwenden. Folgen wir dem Herausgeber und werfen wir einen Blick darauf.

Dieser Artikel führt in ein tiefgreifendes Verständnis der Iteratoren und Generatoren von ES6 ein und teilt sie mit Ihnen. Die Details sind wie folgt:

Probleme mit Schleifenanweisungen


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

Vor ES6 verfolgte diese Standard-For-Schleife den Index des Arrays über Variablen. Wenn mehrere Schleifen verschachtelt sind, müssen mehrere Variablen verfolgt werden, die Codekomplexität wird erheblich erhöht und es treten leicht Fehler durch die falsche Verwendung von Schleifenvariablen auf.

Iteratoren wurden eingeführt, um diese Komplexität zu beseitigen und Fehler in Schleifen zu reduzieren.

Was ist ein Iterator?

Machen wir uns zunächst mit der ES5-Syntax vertraut, um die Erstellung eines Iterators zu simulieren:


function createIterator(items) {
  var i = 0;
  
  return { // 返回一个迭代器对象
    next: function() { // 迭代器对象一定有个next()方法
      var done = (i >= items.length);
      var value = !done ? items[i++] : undefined;
      
      return { // next()方法返回结果对象
        value: value,
        done: done
      };
    }
  };
}

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: undefiend, done: true}"
// 之后所有的调用都会返回相同内容
console.log(iterator.next()); // "{ value: undefiend, done: true}"

Oben geben wir ein Objekt zurück, indem wir die Funktion createIterator() aufrufen. Dieses Objekt verfügt über eine next()-Methode. Wenn die next()-Methode aufgerufen wird, ist das Rückgabeformat {Wert: 1, erledigt: false} Ergebnisobjekt.

Deshalb können wir es so definieren: Ein Iterator ist ein spezielles Objekt mit einer next()-Methode, und jedes Mal, wenn next() aufgerufen wird, wird ein Ergebnisobjekt zurückgegeben.

Mit Hilfe dieses Iteratorobjekts werden wir die Standard-for-Schleife transformieren, die wir gerade gestartet haben [vergessen Sie vorerst die neue for-of-Schleifenfunktion von ES6]:


var colors = ["red", "green", "blue"];
var iterator = createIterator(colors);
while(!iterator.next().done){
  console.log(iterator.next().value);
}

Was? Es geht nur darum, die Schleifenvariable zu eliminieren, aber es erfordert so viel Mühe. Ist der Verlust im Code nicht mehr wert als der Gewinn?

Das ist nicht der Fall. createIterator() muss schließlich nur einmal geschrieben werden und kann jederzeit wiederverwendet werden. Allerdings führt ES6 Generatorobjekte ein, die den Prozess der Iteratorerstellung vereinfachen können.

Was ist ein Generator?

Ein Generator ist eine Funktion, die einen Iterator zurückgibt, dem das Sternchen nach dem Funktionsschlüsselwort (*) übergeben wird. ), um anzugeben, dass das neue Schlüsselwort yield in der Funktion verwendet wird.


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

let iterator = createIterator([1, 2, 3]);

// 既然生成器返回的是迭代器,自然就可以调用迭代器的next()方法
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: undefiend, done: true}"
// 之后所有的调用都会返回相同内容
console.log(iterator.next()); // "{ value: undefiend, done: true}"

Oben haben wir die ES6-Generierung verwendet, was den Prozess der Iteratorerstellung erheblich vereinfacht hat. Wir übergeben ein Item-Array an die Generatorfunktion createIterator(). Innerhalb der Funktion generiert die for-Schleife kontinuierlich neue Elemente aus dem Array und fügt sie jedes Mal in den Iterator ein Wird der Iterator als ()-Methode bezeichnet, läuft die Schleife weiter und stoppt bei der nächsten yield-Anweisung.

So erstellen Sie einen Generator

Ein Generator ist eine Funktion:


function *createIterator(items) { ... }

Ja Geschrieben im Funktionsausdrucksmodus:


let createIterator = function *(item) { ... }

kann auch zu Objekten hinzugefügt werden, Objektliterale im ES5-Stil:


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

let iterator = o.createIterator([1, 2, 3]);

Abkürzung für Objektmethoden im ES6-Stil:


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

let iterator = o.createIterator([1, 2, 3]);

Iterierbares Objekt

In ES6 alle Sammlungsobjekte (Arrays, Set-Sammlungen und Map-Sammlungen) und Zeichenfolgen sind iterierbare Objekte, und iterierbare Objekte sind an Standarditeratoren gebunden.

Hier kommt die lang erwartete neue ES6-Schleifenfunktion for-of:


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

for-of-Schleife, die in On iterable verwendet werden kann Für Objekte wird der Standarditerator für iterierbare Objekte verwendet. Der allgemeine Prozess ist: Bei jeder Ausführung der for-of-Schleife wird die next()-Methode des iterierbaren Objekts aufgerufen und das vom Iterator zurückgegebene Wertattribut des Ergebnisobjekts in einer Variablen gespeichert. Die Schleife wird weiterhin ausgeführt Dieser Vorgang wird ausgeführt, bis das fertige Objekt zurückgegeben wird. Der Wert des Attributs ist wahr.

Wenn Sie nur die Werte in einem Array oder einer Sammlung iterieren müssen, ist die Verwendung einer for-of-Schleife anstelle einer for-Schleife eine gute Wahl.

Zugriff auf den Standarditerator

Iterierbare Objekte verfügen über eine Symbol.iterator-Methode. Wenn die for-of-Schleife ausgeführt wird, ist das Symbol des Farbarrays Rufen Sie die Iterator-Methode auf, um den Standard-Iterator zu erhalten. Dieser Prozess wird hinter der JavaScript-Engine abgeschlossen.

Wir können die Initiative ergreifen, um diesen Standarditerator dazu zu bringen, es zu spüren:


let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();

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

In diesem Code wird das Array über Symbol.iterator abgerufen Der Standarditerator für Werte und wird zum Durchlaufen der Elemente im Array verwendet. Das Ausführen einer for-of-Schleifenanweisung in der JavaScript-Engine ist ein ähnlicher Vorgang.

Verwenden Sie die Eigenschaft Symbol.iterator, um zu erkennen, ob das Objekt ein iterierbares Objekt ist:


function isIterator(object) {
  return typeof object[Symbol.iterator] === "function";
}

console.log(isIterable([1, 2, 3])); // true
console.log(isIterable(new Set())); // true
console.log(isIterable(new Map())); // true
console.log(isIterable("Hello")); // true

Erstellen Sie ein iterierbares Objekt

Wenn wir ein Objekt erstellen, fügen Sie einen Generator zur Symbol.iterator-Eigenschaft hinzu, um es in ein iterierbares Objekt umzuwandeln:


let collection = {
  items: [],
  *[Symbol.iterator]() { // 将生成器赋值给对象的Symbol.iterator属性来创建默认的迭代器
    for(let item of this.items) {
      yield item;
    }
  }
};

collection.items.push(1);
collection.items.push(2);
collection.items.push(3);

for(let x of collection) {
  console.log(x);
}

Eingebaute Iteratoren

Sammlungsobjekte in ES6, Arrays, Set-Sammlungen und Kartensammlungen, alle verfügen über drei integrierte Iteratoren:

  • entries() gibt einen Iterator zurück, dessen Wert aus mehreren Schlüssel-Wert-Paaren besteht. Wenn es sich um ein Array handelt, ist das erste Element die Indexposition. Wenn es sich um eine Menge handelt, sind sowohl das erste als auch das zweite Element Werte.

  • values() gibt einen Iterator zurück, dessen Wert der Wert der Sammlung ist.

  • keys() gibt einen Iterator zurück, dessen Wert alle Schlüsselnamen in der Sammlung sind. Wenn es ein Array ist, wird der Index zurückgegeben; wenn es ein Set ist, wird der Wert zurückgegeben (der Wert des Sets wird sowohl als Schlüssel als auch als Wert verwendet).

不同集合的默认迭代器

每个集合类型都有一个默认的迭代器,在for-of循环中,如果没有显式指定则使用默认的迭代器。按常规使用习惯,我们很容易猜到,数组和Set集合的默认迭代器是values(),Map集合的默认迭代器是entries()。

请看以下示例:


let colors = [ "red", "green", "blue"];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();

data.set("title", "Understanding ECMAScript 6");
data.set("format", "print");

// 与调用colors.values()方法相同
for(let value of colors) {
  console.log(value);
}

// 与调用tracking.values()方法相同
for(let num of tracking) {
  console.log(num);
}

// 与调用data.entries()方法相同
for(let entry of data) {
  console.log(entry);
}

这段代码会输入以下内容:

"red"
"green"
"blue"
1234
5678
9012
["title", "Understanding ECMAScript 6"]
["format", "print"]

for-of循环配合解构特性,操纵数据会更方便:


for(let [key, value] of data) {
  console.log(key + "=" + value);
}

展开运算符操纵可迭代对象


let set = new Set([1, 2, 3, 4, 5]),
  array = [...set];
  
console.log(array); // [1,2,3,4,5]

展开运算符可以操作所有的可迭代对象,并根据默认迭代器来选取要引用的值,从迭代器读取所有值。然后按返回顺序将它们依次插入到数组中。因此如果想将可迭代对象转换为数组,用展开运算符是最简单的方法。

Das obige ist der detaillierte Inhalt vonEinführung in Iteratoren und Generatoren in JavaScript ES6. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn