Maison > interface Web > js tutoriel > Itérateurs ES6 et boucles for.of (tutoriel détaillé)

Itérateurs ES6 et boucles for.of (tutoriel détaillé)

亚连
Libérer: 2018-06-06 17:34:05
original
1450 Les gens l'ont consulté

Cet article présente principalement le résumé d'apprentissage de l'utilisation de l'itérateur ES6 (Iterator) et de la boucle for.of. Maintenant, je le partage avec vous et le donne comme référence.

1. Qu'est-ce qu'un itérateur ?

Le concept du générateur est disponible en Java, Python et d'autres langages, et ES6 a également été ajouté à JavaScript. Iterator nous permet d'éviter d'avoir à initialiser les variables de collection et d'index. Au lieu de cela, nous utilisons la méthode next de l'objet itérateur pour renvoyer la valeur de l'élément suivant de la collection, qui est orientée vers la programmation.

Les itérateurs sont des objets avec une interface spéciale. Contient une méthode next() et l'appel renvoie un objet contenant deux attributs, à savoir value et done. Value représente la valeur de la position actuelle, et done indique si l'itération est terminée. Lorsqu'il est vrai, l'appel de next n'est pas valide.

Le parcours des collections dans ES5 utilise généralement une boucle for. Les tableaux ont également une méthode forEach, et les objets sont for-in Map et Set ont été ajoutés dans ES6, et les itérateurs peuvent gérer toutes les données de collection de manière unifiée. L'itérateur est une interface Tant que votre structure de données expose une interface itérateur, l'itération peut être effectuée. ES6 a créé une nouvelle commande de parcours pour la boucle for...of, et l'interface Iterator est principalement utilisée pour la consommation par for...of.

2. Comment utiliser les itérateurs ?

1. Interface Iterator par défaut

Structure de données Tant que l'interface Iterator sera déployée, nous rendrons cette structure de données "traversable" ( Itérable). ES6 stipule que l'interface Iterator par défaut est déployée dans la propriété Symbol.iterator de la structure de données. En d'autres termes, tant qu'une structure de données contient des données Symbol.iterator, elle peut être considérée comme « traversable » (itérable).

Structure de données native qui peut être consommée par...of

  1. Array

  2. Map

  3. Set

  4. String

  5. TypedArray (un type de tampon générique de longueur fixe qui permet de lire à partir du tampon des données binaires )

  6. L'objet arguments dans la fonction

  7. Objet NodeList

est visible ci-dessus Là il n'y a pas d'objet (Object) dans la structure de données native. Pourquoi ?

C'est parce que l'ordre de parcours des propriétés de l'objet est incertain et doit être spécifié manuellement par le développeur. Essentiellement, le traverseur est un processus linéaire.Pour toute structure de données non linéaire, déployer l'interface du traverseur équivaut à déployer une transformation linéaire.

peut être traité comme suit pour rendre l'objet disponible à la consommation par...de :

// code1
function Obj(value) {
  this.value = value;
  this.next = null;
}
Obj.prototype[Symbol.iterator] = function() {
  var iterator = {
    next: next
  };
  var current = this;
  function next() {
    if (current) {
      var value = current.value;
      current = current.next;
      return {
        done: false,
        value: value
      };
    } else {
      return {
        done: true
      };
    }
  }
  return iterator;
}
var one = new Obj(1);
var two = new Obj(2);
var three = new Obj(3);
one.next = two;
two.next = three;
for (var i of one) {
  console.log(i);
}
// 1
// 2
// 3
Copier après la connexion

2 Lorsque l'interface Iterator est appelée <🎜. >

( 1) Affectation de déstructuration

// code2
let set = new Set().add(&#39;a&#39;).add(&#39;b&#39;).add(&#39;c&#39;);
let [x,y] = set;
// x=&#39;a&#39;; y=&#39;b&#39;
let [first, ...rest] = set;
// first=&#39;a&#39;; rest=[&#39;b&#39;,&#39;c&#39;];
Copier après la connexion
(2) Opérateur d'extension

// code3
// 例一
var str = &#39;hello&#39;;
[...str] // [&#39;h&#39;,&#39;e&#39;,&#39;l&#39;,&#39;l&#39;,&#39;o&#39;]
// 例二
let arr = [&#39;b&#39;, &#39;c&#39;];
[&#39;a&#39;, ...arr, &#39;d&#39;]
// [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;]
Copier après la connexion
(3) Expression de rendement* dans la fonction Générateur (introduite dans le chapitre suivant)

// code4
let generator = function* () {
yield 1;
yield* [2,3,4];
yield 5;
};
var iterator = generator();
iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }
Copier après la connexion
(4) Autres occasions

  1. pour..de

  2. Array.from

  3. Map(), Set(), WeakMap(), WeakSet()

  4. Promise.all()

  5. Promise.race()

3.Avantages de la boucle for...of

Examinons d'abord les inconvénients de la méthode array forEach. :

// code5
myArray.forEach(function (value) {
 console.log(value);
});
Copier après la connexion
Le problème avec cette méthode d'écriture est qu'elle ne peut pas sortir de la boucle forEach à mi-chemin, et ni la commande break ni la commande return ne prendront effet.

Regardez encore, les défauts de l'objet for...en boucle :

for (var index in myArray) {
 console.log(myArray[index]);
};
Copier après la connexion
  1. Le nom de la clé du tableau est un nombre, mais le for. ..in loop Les chaînes sont utilisées comme noms de clé, "0", "1", "2", etc. La boucle

  2. for...in peut non seulement parcourir les noms de clés numériques, mais également parcourir les recommandations de périodes ajoutées manuellement, même les clés de la chaîne prototype.

  3. Dans certains cas, la session en boucle for...in parcourt les noms de clés dans n'importe quel ordre

  4. la traversée for...in est principalement for Conçu pour parcourir des objets, il ne convient pas pour parcourir des tableaux

Alors, quels sont les avantages significatifs de for...of ?

  1. a la même syntaxe concise que for...in, mais n'a pas les défauts de for...in

  2. Différent de la méthode forEach, elle peut être utilisée avec break, continue et return

  3. Fournit une interface d'opération unifiée pour parcourir toutes les structures de données

for (var n of fibonacci) {
 if (n > 1000) {
  break;
  console.log(n);
 }
}
Copier après la connexion

4. Comment utiliser la boucle for...of pour chaque type de données ?

(1) Array

for...of boucle permet de parcourir le tableau pour obtenir des valeurs clés

var arr = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;];
for (let a in arr) {
  console.log(a); // 0 1 2 3
}
for (let a of arr) {
  console.log(a); // a b c d
}
Copier après la connexion
for...of boucle appelle l'interface traverser , l'interface array traverseur ne renvoie que des valeurs avec des index numériques

let arr = [3, 5, 7];
arr.foo = &#39;hello&#39;;
for (let i in arr) {
  console.log(i); // "0", "1", "2", "foo"
}
for (let i of arr) {
  console.log(i); // "3", "5", "7"
}
Copier après la connexion
(2) Structures Map et Set

var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
  console.log(e);
}
// Gecko
// Trident
// Webkit
var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
  console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262
Copier après la connexion
Comme le montre le code ci-dessus , for... Lorsque la boucle of parcourt les structures Map et Set, l'ordre de parcours est basé sur l'ordre dans lequel chaque membre est ajouté à la structure de données. Lors du parcours de la structure Set, elle renvoie une valeur, tandis que lors du parcours. la structure Map, elle renvoie un tableau. Les deux éléments du tableau sont respectivement le nom de clé et la valeur de clé du membre Map actuel.

(3) Objet de type tableau

String

// 普通的字符串遍历
let str = "yuan";
for (let s of str) {
 console.log(s); // y u a n
}

// 遍历含有 32位 utf-16字符的字符串
for (let x of &#39;a\uD83D\uDC0A&#39;) {
 console.log(x);
}
// &#39;a&#39;
// &#39;\uD83D\uDC0A&#39;
Copier après la connexion
Objet DOM NodeList

let paras = document.querySelectorAll("p");
for (let p of paras) {
 p.classList.add("test");
}
Copier après la connexion
objet arguments

function printArgs() {
 for (let x of arguments) {
  console.log(x);
 }
}
printArgs("a", "n");
// "a"
// "n"
Copier après la connexion
Il n'y a pas de classe d'interface Iterator pour le traitement traversant des objets de tableau

Emprunter la méthode Array.from pour le traitement

let arrayLike = {
  length: 2,
  0 : &#39;a&#39;,
  1 : &#39;b&#39;
};
// 报错
for (let x of arrayLike) {
  console.log(x);
}
// 正确
for (let x of Array.from(arrayLike)) {
  console.log(x);
}
Copier après la connexion
(4) Objets

Pour les objets ordinaires , vous ne pouvez pas l'utiliser directement ...de traversée, sinon une erreur sera signalée et l'interface Iterator doit être déployée avant de pouvoir être utilisée. Déployez des deux manières suivantes :

// 方法一:使用 Object.keys 方法讲对象的键名生成一个数组
for (var key of Object.keys(someObject)) {
 console.log(key + ": " + someObject[key]);
}

// 方法二:使用Generator 函数将对象重新包装一下
function * entries(obj) {
  for (let key of Object.keys(obj)) {
    yield[key, obj[key]];
  }
}
for (let[key, value] of entries(obj)) {
  console.log(key, "->", value);
}
// a -> 1
// b -> 2
// c -> 3
Copier après la connexion

三、迭代器应用实例

1、斐波那契数列

下面我们就使用迭代器来自定义自己的一个斐波那契数列组,我们直到斐波那契数列有两个运行前提,第一个前提是初始化的前两个数字为0,1,第二个前提是将来的每一个值都是前两个值的和。这样我们的目标就是每次都迭代输出一个新的值。

var it = { [Symbol.iterator]() {
    return this
  },
  n1: 0,
  n2: 1,
  next() {
    let temp1 = this.n1,
    temp2 = this.n2;
    [this.n1, this.n2] = [temp2, temp1 + temp2]
    return {
      value: temp1,
      done: false
    }
  }
}

for (var i = 0; i < 20; i++) {
  console.log(it.next())
}

// 
  "value": 0,
  "done": false
} {
  "value": 1,
  "done": false
} {
  "value": 1,
  "done": false
} {
  "value": 2,
  "done": false
} {
  "value": 3,
  "done": false
} {
  "value": 5,
  "done": false
}... {
  "value": 2584,
  "done": false
} {
  "value": 4181,
  "done": false
}
Copier après la connexion

2、任务队列迭代器

我们可以定义一个任务队列,该队列初始化时为空,我们将待处理的任务传递后,传入数据进行处理。这样第一次传递的数据只会被任务1处理,第二次传递的只会被任务2处理… 代码如下:

var Task = {
  actions: [],
  [Symbol.iterator]() {
    var steps = this.actions.slice();
    return { [Symbol.iterator]() {
        return this;
      },
      next(...args) {
        if (steps.length > 0) {
          let res = steps.shift()(...args);
          return {
            value: res,
            done: false
          }
        } else {
          return {
            done: true
          }
        }
      }
    }
  }
}

Task.actions.push(function task1(...args) {
  console.log("任务一:相乘") return args.reduce(function(x, y) {
    return x * y
  })
},
function task2(...args) {
  console.log("任务二:相加") return args.reduce(function(x, y) {
    return x + y
  }) * 2
},
function task3(...args) {
  console.log("任务三:相减") return args.reduce(function(x, y) {
    return x - y
  })
});

var it = Task[Symbol.iterator]();
console.log(it.next(10, 100, 2));
console.log(it.next(20, 50, 100)) console.log(it.next(10, 2, 1))
 // 
任务一:相乘 {
  "value": 2000,
  "done": false
}任务二:相加 {
  "value": 340,
  "done": false
}任务三:相减 {
  "value": 7,
  "done": false
}
Copier après la connexion

3、延迟执行

假设我们有一个数据表,我们想按大小顺序依次的获取数据,但是我们又不想提前给他排序,有可能我们根本就不去使用它,所以我们可以在第一次使用的时候再排序,做到延迟执行代码:

var table = {
  "d": 1,
  "b": 4,
  "c": 12,
  "a": 12
}
table[Symbol.iterator] = function() {
  var _this = this;
  var keys = null;
  var index = 0;

  return {
    next: function() {
      if (keys === null) {
        keys = Object.keys(_this).sort();
      }

      return {
        value: keys[index],
        done: index++>keys.length
      };
    }
  }
}

for (var a of table) {
  console.log(a)
} 
// a b c d
Copier après la connexion

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在vue中如何实现微信分享朋友圈,发送朋友

详解如何实现vuex(详细教程)

通过vue.js实现微信支付

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal