javascript 检查某事是否可迭代
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18884249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking whether something is iterable
提问by simonzack
In the MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
在 MDN 文档中:https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
The for...of
construct is described to be able to iterate over "iterable" objects. But is there a good way of deciding whether an object is iterable?
该for...of
构造被描述为能够迭代“可迭代”对象。但是有没有一种好的方法来决定一个对象是否是可迭代的?
I've tried to find common properties for arrays, iterators and generators, but have been unable to do so.
我试图找到数组、迭代器和生成器的通用属性,但一直无法做到。
Aside for doing a for ... of
in a try block and checking for type errors, is there a clean way of doing this?
除了for ... of
在 try 块中执行 a并检查类型错误之外,是否有一种干净的方法来做到这一点?
回答by Tomas Kulich
The proper way to check for iterability is as follows:
检查可迭代性的正确方法如下:
function isIterable(obj) {
// checks for null and undefined
if (obj == null) {
return false;
}
return typeof obj[Symbol.iterator] === 'function';
}
Why this works (iterable protocol in depth): https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
为什么会这样(深度迭代协议):https: //developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
Since we are talking about for..of, I assume, we are in ES6 mindset.
既然我们在谈论 for..of,我假设,我们处于 ES6 思维模式。
Also, don't be surprised that this function returns true
if obj
is a string, as strings iterate over their characters.
此外,true
如果该函数返回obj
字符串,请不要感到惊讶,因为字符串会遍历它们的字符。
回答by adius
Why so verbose?
怎么这么啰嗦?
const isIterable = object =>
object != null && typeof object[Symbol.iterator] === 'function'
回答by Domino
The simplest solution is actually this:
最简单的解决方案实际上是这样的:
function isIterable (value) {
return Symbol.iterator in Object(value);
}
Object
will wrap anything which isn't an object in one, allowing the in
operator to work even if the original value is not an Object. null
and undefined
are turned into empty objects so there's no need for edge case detection, and strings get wrapped into String objects which are iterable.
Object
将任何不是对象的东西包装成一个,in
即使原始值不是对象,也允许运算符工作。null
并undefined
变成空对象,因此不需要边缘情况检测,并且字符串被包装成可迭代的 String 对象。
回答by Francesco Casula
As a sidenote, BEWAREabout the definition of iterable. If you're coming from other languages you would expect that something you can iterate over with, say, a for
loop is iterable. I'm afraid that's not the case here where iterablemeans something that implements the iteration protocol.
作为一个旁注,当心有关的定义迭代。如果你来自其他语言,你会期望你可以迭代的东西,比如for
循环是iterable。恐怕这里的情况并非如此,iterable意味着实现了迭代协议。
To make things clearer all examples above return false
on this object {a: 1, b: 2}
because that object does not implement the iteration protocol. So you won't be able to iterate over it with a for...of
BUTyou still can with a for...in
.
为了使事情更清楚,上面的所有示例都返回false
此对象,{a: 1, b: 2}
因为该对象未实现迭代协议。因此,您将无法使用for...of
BUT对其进行迭代,但您仍然可以使用for...in
.
So if you want to avoid painful mistakes make your code more specific by renaming your method as shown below:
因此,如果您想避免痛苦的错误,请通过如下所示重命名您的方法使您的代码更加具体:
/**
* @param variable
* @returns {boolean}
*/
const hasIterationProtocol = variable =>
variable !== null && Symbol.iterator in Object(variable);
回答by Ortomala Lokni
Nowadays, as already stated, to test if obj
is iterable just do
如今,正如已经说过的,要测试是否obj
可迭代就做
obj != null && typeof obj[Symbol.iterator] === 'function'
Historical answer (no more valid)
历史答案(不再有效)
The for..of
construct is part of the ECMASCript 6th edition Language Specification Draft. So it could change before the final version.
该for..of
构造是 ECMASCRipt 第 6 版语言规范草案的一部分。所以它可以在最终版本之前改变。
In this draft, iterableobjects must have the function iterator
as a property.
在这个草案中,可迭代对象必须具有iterator
作为属性的功能。
You can the check if an object is iterable like this:
您可以像这样检查对象是否可迭代:
function isIterable(obj){
if(obj === undefined || obj === null){
return false;
}
return obj.iterator !== undefined;
}
回答by Kamarey
For asynciterators you should check for the 'Symbol.asyncIterator' instead of 'Symbol.iterator':
对于异步迭代器,您应该检查“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
回答by Seglinglin
If you wanted to check in fact if a variable is an object ({key: value}
) or an array ([value, value]
), you could do that:
如果您想实际检查变量是对象 ( {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);
}