Maison  >  Article  >  interface Web  >  Les es6 peuvent-ils traverser des objets ?

Les es6 peuvent-ils traverser des objets ?

青灯夜游
青灯夜游original
2022-05-19 16:11:083548parcourir

Le "for of" de

es6 ne peut pas traverser les objets. Raison : L'interface Iterator a été introduite dans ES6. Seuls les types de données qui fournissent l'interface Iterator peuvent être parcourus à l'aide de "for-of" tandis que les objets ordinaires ne fournissent pas d'interface Iterator par défaut, donc "for-of" ne peut pas être utilisé pour. traversée.

Les es6 peuvent-ils traverser des objets ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.

Avec le développement continu du front-end, de nombreuses méthodes de boucles lumineuses sont apparues, telles que for, forEach, do..while, for...in, etc. Cependant, ces boucles ont aussi leurs propres scénarios d'application, avantages et inconvénients.

ES6 nous fournit une nouvelle méthode de boucle for...of, qui peut boucler des chaînes, des tableaux et d'autres objets de type tableau. En tant qu'objet Object le plus omniprésent, il va de soi qu'il peut être bouclé ?

Jetons un coup d'œil à l'exemple de code ci-dessous :

{
    // 迭代数组
  const iterable = ['a', 'b'];
  for (const value of iterable) {
    console.log(value);
  }
  // output: a b
}
{
    // 普通对象
    const obj = {
      a: 'A',
      b: 'B'
    }
    for(const item of obj){
      console.log(item)
    }
    // Uncaught TypeError: obj is not iterable
}

oh non, une erreur a été signalée : Uncaught TypeError : obj is not iterable. Cela rappelle que obj n'est pas itérable. Évidemment, il n'est pas possible d'utiliser directement for...of pour parcourir l'objet Object. Uncaught TypeError: obj is not iterable。提示obj是不可迭代的,显然直接用for...of去遍历Object对象是不行的。

那么可以遍历大部分数据结构的for...of为何不能遍历Object对象?

原因:

ES6 中引入了 Iterator,只有提供了 Iterator 接口的数据类型才可以使用 for-of 来循环遍历,而 Array、Set、Map、某些类数组如 arguments 等数据类型都默认提供了 Iterator 接口,所以它们可以使用 for-of 来进行遍历。

而对于普通的对象,for...of结构不能直接使用,会报错,提示obj is not iterable,也就是说普通对象默认没有Iterator接口,必须部署了 Iterator 接口后才能使用。

怎么解决?让for-of 遍历对象

那么原因清楚了,该怎么解决呢?能不能为对象已经其它的一些数据类型提供 Iterator 接口呢

答案是可以的,ES6 同时提供了 Symbol.iterator 属性,只要一个数据结构有这个属性,就会被视为有 Iterator 接口,接着就是如何实现这个接口了,如下就是一个最简实现:

newObj[Symbol.iterator] = function(){
    let index = 0
        , self = this
        , keys = Object.keys( self )
        ;
    
    return {
        next(){
            if( index < keys.length ){
                return {
                    value: self[keys[index++]]
                    , done: false
                };
            }
            else{
                return {
                    value: undefined
                    , done: true
                }
            }
        }
    };
};

仔细看一下发现就会发现 Symbol.iterator 接口其实是一个 Generator 函数,那么就可以简化代码:

newObj[Symbol.iterator] = function* (){
    let keys = Object.keys( this )
        ;
    
    for(let i = 0, l = keys.length; i < l; i++){
        yield this[keys[i]];
    }
}

for(let v of newObj){
    console.log( v );
}
// 输出结果
// 5
// 6

值得注意的是 Object.keys 碰巧解决了之前 for-in 遇到的继承问题

这样满足了我们的期望,使用 for-of 来遍历对象,但是好像哪里不对,我们遍历对象时一般都是期望同时输出 key 和 value 的,这样调整一下代码

newObj[Symbol.iterator] = function* (){
    let keys = Object.keys( this )
        ;
    
    for(let i = 0, l = keys.length; i < l; i++){
        yield {
            key: keys[i]
            , value: this[keys[i]]
        };
    }
}

for(let v of newObj){
    console.log( v );
}
// 输出结果
// {key: "e", value: 5}
// {key: "f", value: 6}

这样返回了一个对象,似乎又很不舒服,我们能不能尝试一些解构赋值呢。。。

for(let {key, value} of newObj){
    console.log(key, value );
}
// 输出结果
// e 5
// f 6

这样似乎非常完美了。。。

扩展知识:for-of和其他循环的区别

Iterator a été introduit dans ES6. Seuls les types de données qui fournissent l'interface Iterator peuvent être parcourus à l'aide de types de données tels que Array, Set, Map et certains tableaux tels que les arguments. L'interface est fournie par défaut, elles peuvent donc être parcourues en utilisant for-of.
循环名称 循环对象 是否可中断循环 是否有返回值
for for循环体的length 可以 无返回值
forEach 仅可循环数组、map、set等,不可循环字符串、普通对象 不可以 无返回值
do...while 满足某种条件,则可一直循环,至少循环一次 可以 无返回值
while 满足某种条件,则可一直循环 可以 无返回值
map 组成新的数组成员,仅可循环数组,不可循环字符串、普通对象,set、map 不可中断 返回新数组,不影响原数组
filter 过滤数组成员,仅可循环数组,不可循环字符串、普通对象,set、map 不可中断 返回新数组,不影响原数组
for...in 可循环数组、对象,不可循环map、set。可遍历数字键名,还可遍历手动添加的其他键,甚至包括原型链上的键 可以 无返回值
for...of Alors pourquoi pour...of, qui peut traverser la plupart des structures de données, ne peut-il pas traverser les objets Object ? Raison :

Pour les objets ordinaires, la structure for...of ne peut pas être utilisée directement, et une erreur sera signalée, indiquant que obj n'est pas itérable, ce qui signifie que les objets ordinaires n'ont pas une interface Iterator par défaut et doit être déployée. Elle ne peut être utilisée qu'après acquisition de l'interface Iterator. Comment le résoudre ? Laissez for-of traverser l'objet

🎜Donc la raison est claire, comment la résoudre ? Peut-il fournir une interface Iterator pour les objets et d'autres types de données ? La réponse est oui. ES6 fournit également l'attribut Symbol.iterator. Tant qu'une structure de données possède cet attribut, elle sera considérée comme ayant une interface Iterator. Voici comment Après avoir implémenté cette interface, voici l'implémentation la plus simple : 🎜rrreee🎜Si vous regardez attentivement, vous constaterez que l'interface Symbol.iterator est en fait une fonction Générateur, alors le code peut être simplifié : 🎜rrreee🎜Cela vaut la peine notant que Object.keys arrive à résoudre Nous avons déjà résolu le problème d'héritage rencontré par for-in🎜🎜Cela répond à nos attentes et utilise for-of pour parcourir l'objet, mais quelque chose ne semble pas correct Lorsque nous traversons l'objet, nous nous attendons généralement. pour afficher la clé et la valeur en même temps. Ajustez-le comme ceci. Le code 🎜rrreee🎜 renvoie un objet comme celui-ci, ce qui semble très inconfortable. Pouvons-nous essayer une affectation de déstructuration ? . . 🎜rrreee🎜Cela semble parfait. . . 🎜🎜🎜Développez vos connaissances : la différence entre les boucles for-of et les autres boucles🎜🎜Si la boucle peut être interrompue🎜🎜for🎜🎜for La longueur🎜🎜 du corps de la boucle peut être🎜🎜aucune valeur de retour🎜🎜🎜forEach🎜🎜ne peut boucler qu'un tableau, map, set etc. Les chaînes et les objets ordinaires ne peuvent pas être bouclés🎜🎜Non🎜🎜Aucune valeur de retour🎜🎜🎜do... while🎜🎜Si certaines conditions sont remplies, vous pouvez boucler pour toujours, au moins boucler Une fois 🎜🎜peut 🎜🎜aucune valeur de retour🎜🎜🎜pendant🎜🎜si certaines conditions sont remplies, il peut continuer à boucler🎜🎜peut🎜🎜aucun retour value🎜🎜🎜map🎜🎜 forme un nouveau membre du tableau. Il ne peut boucler que des tableaux, pas des chaînes et des objets ordinaires. Set et map🎜🎜ne peuvent pas être interrompus🎜🎜Renvoie un nouveau tableau sans. affectant le tableau d'origine🎜🎜🎜 filter🎜🎜Filtrer les membres du tableau, uniquement les tableaux bouclables, pas les chaînes bouclables, les objets ordinaires, l'ensemble, la carte🎜🎜ne peut pas être interrompu🎜🎜Renvoie un nouveau tableau, n'affecte pas le tableau d'origine🎜🎜🎜 for...in🎜🎜peut boucler tableau, objet, mais ne peut pas boucler map, set code>. Il peut parcourir les noms de clés numériques et d'autres clés ajoutées manuellement, même les clés de la chaîne prototype🎜🎜Can🎜🎜Aucune valeur de retour🎜🎜<tr>🎜<code>for...of🎜🎜 Cyclisme des objets itérables , objets ordinaires non cycliques (traversée de structure de données unifiée) 🎜🎜 Oui 🎜🎜 Aucune valeur de retour 🎜🎜🎜🎜🎜 [Recommandations associées : 🎜tutoriel vidéo javascript🎜, 🎜front-end web🎜]🎜
Nom de la boucle Objet de boucleY a-t-il une valeur de retour

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!

Déclaration:
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