Maison > interface Web > js tutoriel > le corps du texte

Comment utiliser l'itérateur ES6 (Iterator) et la boucle for.of

小云云
Libérer: 2018-02-09 10:05:18
original
1129 Les gens l'ont consulté

Cet article vous présente principalement le résumé d'apprentissage de l'utilisation de l'itérateur ES6 (Iterator) et de la boucle for.of. L'éditeur pense qu'il est plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.

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

Le concept de 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(). 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 d'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

Tant que l'interface Iterator est déployée dans la structure de données, nous appellerons cette structure de données "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.

Effectuez le traitement suivant pour rendre l'objet disponible à la consommation par pour...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éconstruction

// code2
let set = new Set().add('a').add('b').add('c');
let [x,y] = set;
// x='a'; y='b'
let [first, ...rest] = set;
// first='a'; rest=['b','c'];
Copier après la connexion

(2) Opérateur Spread

// code3
// 例一
var str = 'hello';
[...str] // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
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

Regardons 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 façon d'écrire est que , ne peut pas sortir de la boucle forEach à mi-chemin, et ni la commande break ni la commande return ne prennent 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 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 les types de données ?

(1) Array

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

var arr = ['a', 'b', 'c', 'd'];
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 = 'hello';
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 on peut le voir sur le code ci-dessus, for ...of parcourt les structures Map et Set dans l'ordre dans lequel chaque membre est ajouté à la structure de données Lorsque la structure Set est parcourue, une valeur est renvoyée, tandis que lorsque la structure Map est parcourue, un tableau est renvoyé. Les deux membres sont 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 'a\uD83D\uDC0A') {
 console.log(x);
}
// 'a'
// '\uD83D\uDC0A'
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

Traitement traversant des objets de tableau sans classe d'interface Iterator

Méthode Borrow Array.from pour le traitement

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

(4 ) Objet

Pour les objets ordinaires, vous ne pouvez pas utiliser directement for...of pour parcourir, sinon une erreur sera signalée et l'interface Iterator doit être déployée avant de pouvoir être utilisée. Déployez selon les deux méthodes 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

3. Exemples d'applications Iterator

.

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

四、结语

本章内容,重点是明白 Iterator 接口的机制,以及 for...of 循环的使用方法。

相关推荐:

ES6可迭代协议和迭代器协议详解

关于PHP聚合式迭代器接口IteratorAggregate用法分享

关于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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!