在MDN文档中:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
该for...of构造被描述为能够迭代"可迭代"对象.但有没有一种很好的方法来决定一个对象是否可迭代?
我试图找到数组,迭代器和生成器的公共属性,但一直无法这样做.
除了for ... of在try块中执行并检查类型错误之外,还有一种干净的方法吗?
Tom*_*ich 109
检查可迭代性的正确方法如下:
function isIterable(obj) {
// checks for null and undefined
if (obj == null) {
return false;
}
return typeof obj[Symbol.iterator] === 'function';
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样(深度可迭代协议):https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
因为我们正在讨论for..of,我认为,我们处于ES6心态.
此外,true如果obj是一个字符串,这个函数返回时不要感到惊讶,因为字符串会迭代它们的字符.
adi*_*ius 22
为什么这么冗长?
const isIterable = object =>
object != null && typeof object[Symbol.iterator] === 'function'
Run Code Online (Sandbox Code Playgroud)
dot*_*hen 22
如果您问“是否可foo迭代”,那么您可能来自一种语言(PHP、Python),该问题只有一个答案。在现代 Javascript 中,有不同类型的可迭代。因此,您必须根据您想要对变量执行的操作来检查迭代的能力。
forEach()测试使用with !!foo.forEach, 在数组上返回 true进行迭代的能力。for..of测试使用with !!foo[Symbol.iterator], 在数组或字符串上返回 true进行迭代的能力。for..in测试使用with !!Object.keys(Object(foo)).length, 在数组、字符串或对象上返回 true进行迭代的能力。让我们定义一些变量:
\nconst someNumber = 42;\n42\n\nconst someArray = [1,2,3];\n(3) [1, 2, 3]\n\nconst someString = "Hello";\n"Hello, world!"\n\nconst someObject = {a:"A", b:"B"};\n{a: "A", b: "B"}\nRun Code Online (Sandbox Code Playgroud)\nforEach()哪些类型可以用 进行迭代forEach(),用 进行测试!!foo.forEach:
someNumber.forEach(x=>console.log(x));\nVM1526:1 Uncaught TypeError: someNumber.forEach is not a function at <anonymous>:1:12\n\nsomeArray.forEach(x=>console.log(x));\nVM916:1 1\nVM916:1 2\nVM916:1 3\nundefined\n\nsomeString.forEach(x=>console.log(x));\nVM957:1 Uncaught TypeError: someString.forEach is not a function at <anonymous>:1:12\n\nsomeObject.forEach(x=>console.log(x));\nVM994:1 Uncaught TypeError: someObject.forEach is not a function at <anonymous>:1:12\nRun Code Online (Sandbox Code Playgroud)\n只有数组似乎可以使用 进行迭代forEach()。
for..of哪些类型可以用 进行迭代for..of,用 进行测试!!foo[Symbol.iterator]:
for (x of someNumber) { console.log(x); }\nVM21027:1 Uncaught TypeError: someNumber is not iterable at <anonymous>:1:11\n \nfor (x of someArray) { console.log(x); }\nVM21047:1 1\nVM21047:1 2\nVM21047:1 3\nundefined\n\nfor (x of someString) { console.log(x); }\nVM21065:1 H\nVM21065:1 e\nVM21065:1 l\nVM21065:1 l\nVM21065:1 o\nundefined\n\nfor (x of someObject) { console.log(x); }\nVM21085:1 Uncaught TypeError: someObject is not iterable at <anonymous>:1:11\nRun Code Online (Sandbox Code Playgroud)\n\xe2\x80\x8b数组和字符串似乎可以使用 for..of 进行迭代,但对象则不然。Number 和 Object 都抛出了错误。
\nfor..in哪些类型可以用 进行迭代for..in,用 进行测试!!Object.keys(Object(foo)).length:
for (x in someNumber) { console.log(x); }\nundefined\n\nfor (x in someArray) { console.log(x); }\nVM20918:1 0\nVM20918:1 1\nVM20918:1 2\nundefined\n\nfor (x in someString) { console.log(x); }\nVM20945:1 0\nVM20945:1 1\nVM20945:1 2\nVM20945:1 3\nVM20945:1 4\nundefined\n\nfor (x in someObject) { console.log(x); }\nVM20972:1 a\nVM20972:1 b\nundefined\nRun Code Online (Sandbox Code Playgroud)\n\xe2\x80\x8b数组、字符串和对象似乎都可以使用for..in. 尽管它没有迭代,但 Number 没有抛出错误。
在现代 ES6 Javascript 中,我发现forEach使用频率远高于for..in或for..of。但 Javascript 开发人员必须意识到这三种方法之间的差异,以及每种方法的不同行为。
Dom*_*ino 12
最简单的解决方案实际上是这样的:
function isIterable (value) {
return Symbol.iterator in Object(value);
}
Run Code Online (Sandbox Code Playgroud)
Object会将不是对象的任何东西包装在一起,in即使原始值不是对象,也允许操作员进行工作。null并被undefined转换为空对象,因此无需进行边缘大小写检测,并且字符串被包装为可迭代的String对象。
作为一个旁注,当心有关的定义迭代.如果你来自其他语言,你会期望你可以迭代一些东西,比如说for循环是可迭代的.我担心这不是这里的情况,其中iterable意味着实现迭代协议的东西.
为了使事情更清楚,上面的所有示例都返回false此对象,{a: 1, b: 2}因为该对象不实现迭代协议.所以你将无法用它来迭代它,for...of 但你仍然可以使用for...in.
因此,如果您想避免痛苦的错误,请通过重命名您的方法使您的代码更具体,如下所示:
/**
* @param variable
* @returns {boolean}
*/
const hasIterationProtocol = variable =>
variable !== null && Symbol.iterator in Object(variable);
Run Code Online (Sandbox Code Playgroud)
对于异步迭代器,您应该检查“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
Run Code Online (Sandbox Code Playgroud)
如果对象具有该属性,Symbol.iterator那么它是可迭代的。然后我们可以obj像这样简单地检查是否可迭代
function isIterable(x: unknown): boolean {
return !!x?.[Symbol.iterator];
}
Run Code Online (Sandbox Code Playgroud)
或者作为箭头函数
const isIterable = (x: unknown): boolean => !!x?.[Symbol.iterator];
Run Code Online (Sandbox Code Playgroud)
function isIterable(x: unknown): boolean {
return !!x?.[Symbol.iterator];
}
Run Code Online (Sandbox Code Playgroud)
const isIterable = (x: unknown): boolean => !!x?.[Symbol.iterator];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29271 次 |
| 最近记录: |