在MDN文档中:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
for...of
构造被描述为能够迭代“可迭代”对象。但有没有一种很好的方法来判断一个对象是否可以迭代?
我试图找到数组,迭代器和生成器的公共属性,但一直无法这样做。
除了在try块中执行for ... of
并检查类型错误之外,还有一种干净的方法吗?
答案 0 :(得分:92)
检查可迭代性的正确方法如下:
function isIterable(obj) {
// checks for null and undefined
if (obj == null) {
return false;
}
return typeof obj[Symbol.iterator] === 'function';
}
为什么这样做(深度可迭代协议):https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
由于我们正在讨论for..of,我认为,我们处于ES6心态。
另外,如果true
是一个字符串,则此函数返回obj
并不会感到惊讶,因为字符串会迭代它们的字符。
答案 1 :(得分:15)
为什么这么详细?
const isIterable = object =>
object != null && typeof object[Symbol.iterator] === 'function'
答案 2 :(得分:6)
作为旁注,请注意关于可迭代的定义。如果您来自其他语言,那么您可以期待可以迭代的内容,例如,for
循环可迭代。我担心这里的情况不是可迭代意味着实现iteration protocol的东西。
为了使事情更清楚,上面的所有示例都会在此对象false
上返回{a: 1, b: 2}
,因为该对象未实现迭代协议。因此,您无法使用for...of
但对其进行迭代,您仍然可以使用for...in
。
因此,如果您想避免痛苦的错误,请通过重命名您的方法使您的代码更具体,如下所示:
/**
* @param variable
* @returns {boolean}
*/
const hasIterationProtocol = variable =>
variable !== null && Symbol.iterator in Object(variable);
答案 3 :(得分:3)
最简单的解决方案实际上是这样的:
function isIterable (value) {
return Symbol.iterator in Object(value);
}
Object
将所有不是对象的东西包装在一起,即使原始值不是对象,也允许in
运算符工作。 null
和undefined
变成了空对象,因此不需要边缘情况检测,并且字符串被包装成可迭代的String对象。
答案 4 :(得分:2)
如今,如前所述,要测试obj
是否可迭代,只需执行
obj != null && typeof obj[Symbol.iterator] === 'function'
for..of
构造是ECMASCript第6版语言规范草案的一部分。所以它可能会在最终版本之前发生变化。
在此草案中,iterable个对象必须具有函数iterator
作为属性。
您可以检查对象是否可以像这样迭代:
function isIterable(obj){
if(obj === undefined || obj === null){
return false;
}
return obj.iterator !== undefined;
}
答案 5 :(得分:1)
对于异步迭代器,您应该检查'Symbol.asyncIterator'而不是'Symbol.iterator':
async function* doSomething(i) {
yield 1;
yield 2;
}
let obj = doSomething();
console.log(typeof obj[Symbol.iterator] === 'function'); // false
console.log(typeof obj[Symbol.asyncIterator] === 'function'); // true
答案 6 :(得分:0)
如果您实际上想检查变量是对象({key: value}
)还是数组([value, value]
),则可以执行以下操作:
const isArray = function (a) {
return Array.isArray(a);
};
const isObject = function (o) {
return o === Object(o) && !isArray(o) && typeof o !== 'function';
};
function isIterable(variable) {
return isArray(variable) || isObject(variable);
}
答案 7 :(得分:0)
我一直在寻找for ... in
的支票,并决定了以下内容。
isIterable (value) {
// add further checks here based on need.
return Object.keys(Object(value)).length > 0
}
对于所有可迭代且具有至少一个值的值,它将返回true
。
因此,空字符串,空数组,空对象等将返回false
。
但是{a: 'x', b:'y'}
将返回true
。