--- title: 'TypeError: ''x'' is not iterable' slug: Web/JavaScript/Reference/Erreurs/is_not_iterable tags: - Error - JavaScript - Reference - TypeError translation_of: Web/JavaScript/Reference/Errors/is_not_iterable ---
TypeError: 'x' is not iterable (Firefox, Chrome) TypeError: 'x' is not a function or its return value is not iterable (Chrome)
{{jsxref("TypeError")}}
La valeur passée comme opérande droit de for…of
ou comme argument d'une fonction telle que {{jsxref("Promise.all")}} ou {{jsxref("TypedArray.from")}} n'est pas un objet itérable. Un objet itérable peut être un objet itérable natif tel qu'un objet {{jsxref("Array")}}, {{jsxref("String")}} ou {{jsxref("Map")}} ou le résultat d'un générateur ou un objet qui implémente le protocole itérable.
En JavaScript, les objets ne sont pas itérables car ils n'implémentent pas le protocole itérable. On ne peut donc pas utiliser for...of
afin d'en parcourir les propriétés.
var obj = { 'France': 'Paris', 'England': 'London' }; for (let p of obj) { // TypeError: obj is not iterable // … }
Si on souhaite utiliser un itérateur pour parcourir les propriétés (leurs noms ou leurs valeurs), on pourra utiliser les méthodes {{jsxref("Object.keys")}} ou {{jsxref("Object.entries")}} qui fournissent des itérateurs :
var obj = { 'France': 'Paris', 'England': 'London' }; // On parcourt les noms des propriétés for (let country of Object.keys(obj)) { var capital = obj[country]; console.log(country, capital); } for (const [country, capital] of Object.entries(obj)) console.log(country, capital);
On pourrait également utiliser un objet {{jsxref("Map")}} :
var map = new Map; map.set('France', 'Paris'); map.set('England', 'London'); // On parcourt les noms des propriétés for (let country of map.keys()) { let capital = map[country]; console.log(country, capital); } for (let capital of map.values()) console.log(capital); for (const [country, capital] of map.entries()) console.log(country, capital);
Les générateurs sont des fonctions qui, lorsqu'elles sont appelées, produisent des objets itérables.
function* generate(a, b) { yield a; yield b; } for (let x of generate) // TypeError: generate is not iterable console.log(x);
Lorsqu'elles ne sont pas appelées, l'objet {{jsxref("Function")}} correspondant au générateur peut être appelé mais il n'est pass itérable. Il ne faut donc pas oublier d'invoquer le générateur afin de parcourir les valeurs de l'itérateur qu'il produit.
function* generate(a, b) { yield a; yield b; } for (let x of generate(1,2)) console.log(x);
Les itérables spécifiques (custom iterables) peuvent être créés en implémentant la méthode {{jsxref("Symbol.iterator")}}. En implémentant cette méthode, il faut s'assurer que la valeur renvoyée est un objet qui est un itérateur. Autrement dit, l'objet renvoyé doit posséder une méthode next()
.
const monIterableVide = { [Symbol.iterator]() { return [] // [] est un iterable mais pas un itérateur // car il n'a pas de méthode next } } Array.from(monIterableVide); // TypeError: monIterableVide is not iterable
Voici une implémentation correcte :
const monIterableVide = { [Symbol.iterator]() { return [][Symbol.iterator]() } } Array.from(monIterableVide); // []
for…of