类型错误:'x' 不可迭代
当作为 for...of
的右侧、作为函数(例如 Promise.all
或 TypedArray.from
)的参数或作为数组 解构赋值 的右侧给出的值不是 可迭代对象 时,会发生 JavaScript 异常 "不可迭代"。
¥The JavaScript exception "is not iterable" occurs when the value which is given as the
right-hand side of for...of
,
as argument of a function such as Promise.all
or TypedArray.from
,
or as the right-hand side of an array destructuring assignment,
is not an iterable object.
信息
错误类型
什么地方出了错?
¥What went wrong?
作为 for...of
右侧、或作为 Promise.all
或 TypedArray.from
等函数的参数、或作为数组 解构赋值 右侧给出的值不是 可迭代对象。可迭代可以是内置可迭代类型(例如 Array
、String
或 Map
)、生成器结果或实现 可迭代协议 的对象。
¥The value which is given as the right-hand side of for...of
,
or as argument of a function such as Promise.all
or TypedArray.from
,
or as the right-hand side of an array destructuring assignment,
is not an iterable object.
An iterable can be a built-in iterable type such as
Array
, String
or Map
, a generator result, or
an object implementing the iterable protocol.
示例
数组解构不可迭代的数组
¥Array destructuring a non-iterable
const myobj = { arrayOrObjProp1: {}, arrayOrObjProp2: [42] };
const {
arrayOrObjProp1: [value1],
arrayOrObjProp2: [value2],
} = myobj; // TypeError: object is not iterable
console.log(value1, value2);
在某些运行时环境中,不可迭代可能会变成 undefined
。
¥The non-iterable might turn to be undefined
in some runtime environments.
迭代对象属性
¥Iterating over Object properties
在 JavaScript 中,Object
不可迭代,除非它们实现了 可迭代协议。因此,不能使用 for...of
来迭代对象的属性。
¥In JavaScript, Object
s are not iterable unless they implement
the iterable protocol.
Therefore, you cannot use for...of
to iterate over the properties of an object.
const obj = { France: "Paris", England: "London" };
for (const p of obj) {
// …
} // TypeError: obj is not iterable
相反,你必须使用 Object.keys
或 Object.entries
来迭代对象的属性或条目。
¥Instead you have to use Object.keys
or Object.entries
, to
iterate over the properties or entries of an object.
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
:
¥Another option for this use case might be to use a Map
:
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);
}
迭代生成器
¥Iterating over a generator
生成器功能 是你调用以生成可迭代对象的函数。
¥Generator functions are functions you call to produce an iterable object.
function* generate(a, b) {
yield a;
yield b;
}
for (const x of generate) {
console.log(x);
} // TypeError: generate is not iterable
当它们不被调用时,生成器对应的 Function
对象是可调用的,但不可迭代。调用生成器会生成一个可迭代对象,该对象将迭代生成器执行期间生成的值。
¥When they are not called, the Function
object corresponding to the
generator is callable, but not iterable. Calling a generator produces an iterable
object which will iterate over the values yielded during the execution of the
generator.
function* generate(a, b) {
yield a;
yield b;
}
for (const x of generate(1, 2)) {
console.log(x);
}
迭代自定义可迭代对象
¥Iterating over a custom iterable
可以通过实现 Symbol.iterator
方法来创建自定义迭代。你必须确定你的迭代器方法返回一个迭代器对象,也就是说它必须有一个 next 方法。
¥Custom iterables can be created by implementing the
Symbol.iterator
method. You must be certain that your iterator method
returns an object which is an iterator, which is to say it must have a next method.
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
这是一个正确的实现:
¥Here is a correct implementation:
const myEmptyIterable = {
[Symbol.iterator]() {
return [][Symbol.iterator]();
},
};
Array.from(myEmptyIterable); // []
也可以看看
¥See also