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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 13:33:10  来源:igfitidea点击:

Checking whether something is iterable

javascript

提问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...ofconstruct 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 ... ofin 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 trueif objis 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);
}

Objectwill wrap anything which isn't an object in one, allowing the inoperator to work even if the original value is not an Object. nulland undefinedare 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即使原始值不是对象,也允许运算符工作。nullundefined变成空对象,因此不需要边缘情况检测,并且字符串被包装成可迭代的 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 forloop 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 falseon 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...ofBUTyou still can with a for...in.

为了使事情更清楚,上面的所有示例都返回false此对象,{a: 1, b: 2}因为该对象未实现迭代协议。因此,您将无法使用for...ofBUT对其进行迭代,您仍然可以使用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 objis iterable just do

如今,正如已经说过的,要测试是否obj可迭代就做

obj != null && typeof obj[Symbol.iterator] === 'function' 

Historical answer (no more valid)

历史答案(不再有效)

The for..ofconstruct 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 iteratoras 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);
}