TypeError: 'x' is not iterable
當以下值不是可迭代物件時,會發生 JavaScript 異常“不可迭代”:擴充套件到陣列或函式呼叫的值,作為for...of的右側,作為Promise.all或Set()等函式的引數,或者作為陣列解構的右側。當Array.fromAsync()或for await...of與非非同步可迭代物件一起使用時,也會遇到此錯誤。
訊息
TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function (V8-based & Safari) TypeError: %Array%.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function (V8-based & Safari) TypeError: Array.fromAsync requires that the property of the first argument, items[Symbol.asyncIterator], when exists, be a function (V8-based & Safari) TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator)) (V8-based) TypeError: x is not async iterable (V8-based) TypeError: x is not iterable (V8-based & Firefox) TypeError: undefined is not a function (near '...y of x...') (Safari) TypeError: Array.from: no function (Safari) TypeError: Type error (Safari)
錯誤型別
TypeError
哪裡出錯了?
擴充套件到陣列或函式呼叫、作為for...of的右側、作為Promise.all或Set()等函式的引數,或者作為陣列解構模式源的值不是可迭代物件。可迭代物件可以是內建的可迭代型別,例如Array、String或Map,生成器結果,或者實現可迭代協議的物件。
js
const nonIterable1 = {};
const nonIterable2 = { [Symbol.iterator]: 1 };
[...nonIterable1];
Math.max(...nonIterable1);
for (const x of nonIterable1);
new Set(nonIterable1);
Array.from(nonIterable2);
new Int8Array(nonIterable2);
const [] = nonIterable1;
示例
解構非可迭代陣列
js
const myObj = { arrayOrObjProp1: {}, arrayOrObjProp2: [42] };
const {
arrayOrObjProp1: [value1],
arrayOrObjProp2: [value2],
} = myObj; // TypeError: object is not iterable
console.log(value1, value2);
在某些執行時環境中,非可迭代物件可能會變為undefined。
迭代物件屬性
在 JavaScript 中,Object除非實現可迭代協議,否則不可迭代。因此,您不能使用for...of迭代物件的屬性。
js
const obj = { France: "Paris", England: "London" };
for (const p of obj) {
// …
} // TypeError: obj is not iterable
相反,您必須使用Object.keys或Object.entries來迭代物件的屬性或條目。
js
const obj = { France: "Paris", England: "London" };
// Iterate over the property names:
for (const country of Object.keys(obj)) {
const capital = obj[country];
console.log(country, capital);
}
for (const [country, capital] of Object.entries(obj)) {
console.log(country, capital);
}
此用例的另一個選項可能是使用Map
js
const map = new Map();
map.set("France", "Paris");
map.set("England", "London");
// Iterate over the property names:
for (const country of map.keys()) {
const capital = map.get(country);
console.log(country, capital);
}
for (const capital of map.values()) {
console.log(capital);
}
for (const [country, capital] of map.entries()) {
console.log(country, capital);
}
迭代生成器
生成器函式是您呼叫以生成可迭代物件的函式。
js
function* generate(a, b) {
yield a;
yield b;
}
for (const x of generate) {
console.log(x);
} // TypeError: generate is not iterable
當它們未被呼叫時,與生成器對應的Function物件是可呼叫的,但不可迭代。呼叫生成器會生成一個可迭代物件,該物件將在生成器執行期間迭代產生的值。
js
function* generate(a, b) {
yield a;
yield b;
}
for (const x of generate(1, 2)) {
console.log(x);
}
迭代自定義可迭代物件
可以透過實現Symbol.iterator方法來建立自定義可迭代物件。您必須確保您的迭代器方法返回一個迭代器物件,也就是說它必須有一個 next 方法。
js
const myEmptyIterable = {
[Symbol.iterator]() {
return []; // [] is iterable, but it is not an iterator — it has no next method.
},
};
Array.from(myEmptyIterable); // TypeError: myEmptyIterable is not iterable
這是一個正確的實現
js
const myEmptyIterable = {
[Symbol.iterator]() {
return [][Symbol.iterator]();
},
};
Array.from(myEmptyIterable); // []