注意:问题仍然适用于 for...of 循环。> 不要使用 for...in 来迭代数组,用它来迭代对象的属性。也就是说,这
我了解 JavaScript 中的基本 for…in
语法如下所示:
for (var obj in myArray) {
// ...
}
但是如何获得循环计数器/索引?
我知道我可能会做类似的事情:
var i = 0;
for (var obj in myArray) {
alert(i)
i++
}
甚至是老好人:
for (var i = 0; i < myArray.length; i++) {
var obj = myArray[i]
alert(i)
}
但我宁愿使用更简单的 for-in
循环。我认为它们看起来更好,更有意义。
有没有更简单或更优雅的方法?
在 Python 中很容易:
for i, obj in enumerate(myArray):
print i
alert(obj)
?
for…in
迭代属性名称,而不是值,并且这样做 in an unspecified order(是的,即使在 ES6 之后也是如此)。您不应该使用它来迭代数组。对他们来说,有 ES5 的 forEach
方法将值和索引都传递给你给它的函数:
var myArray = [123, 15, 187, 32];
myArray.forEach(function (value, i) {
console.log('%d: %s', i, value);
});
// Outputs:
// 0: 123
// 1: 15
// 2: 187
// 3: 32
或者 ES6 的 Array.prototype.entries
,它现在支持当前浏览器版本:
for (const [i, value] of myArray.entries()) {
console.log('%d: %s', i, value);
}
对于一般的可迭代对象(您将使用 for…of
循环而不是 for…in
),没有内置任何内容,但是:
function* enumerate(iterable) {
let i = 0;
for (const x of iterable) {
yield [i, x];
i++;
}
}
for (const [i, obj] of enumerate(myArray)) {
console.log(i, obj);
}
如果您确实是指 for…in
– 枚举属性 – 您将需要一个额外的计数器。 Object.keys(obj).forEach
可以工作,但它只包含 自己的 属性; for…in
包括原型链上任意位置的可枚举属性。
在 ES6 中,最好使用 for... of
循环。您可以像这样在 for... of
中获取索引
for (let [index, val] of array.entries()) {
// your code goes here
}
请注意,Array.entries()
返回 an iterator,这使得它可以在 for-of 循环中工作;不要将此与 Object.entries() 混淆,后者返回一个键值对的数组。
entries()
返回一个空对象:{}
。知道为什么会这样吗?我的 array
是一个对象数组。
next()
方法的对象,每次调用它都会返回数组中的后续条目。里面没有(可见的)数据;您可以通过调用 next()
获取底层对象中的数据,这在幕后执行。抄送@tonyg
await
按顺序工作,而 forEach
不能。
这个怎么样
let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))
其中 array.forEach
此方法有一个 index
参数,它是数组中正在处理的当前元素的索引。
break
不可用。
小数组集合的解决方案:
for (var obj in arr) {
var i = Object.keys(arr).indexOf(obj);
}
arr - ARRAY,obj - 当前元素的 KEY,i - COUNTER/INDEX
注意:方法keys()不适用于IE版本<9,你应该使用Polyfill代码。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
var i = 0;
和 i++;
更短且更高效。此外,它不适用于不是自己的属性的可枚举属性。
For-in-loops 遍历对象的属性。不要将它们用于数组,即使它们有时会起作用。
对象属性没有索引,它们都是相等的,不需要按确定的顺序运行。如果您想计算属性,则必须设置额外的计数器(就像您在第一个示例中所做的那样)。
循环数组:
var a = [];
for (var i=0; i<a.length; i++) {
i // is the index
a[i] // is the item
}
循环对象:
var o = {};
for (var prop in o) {
prop // is the property name
o[prop] // is the property value - the item
}
(var i=0; i<a.length; i++)
。使用(var i=0, var len = a.length; i<len; i++)
var i=0; i<a.length; i++)
是标准循环模式,无论如何都被每个体面的 javascript 引擎优化。
var i=0; i<a.length; i++
是最佳做法。
正如其他人所说,您不应该使用 for..in 来遍历数组。
for ( var i = 0, len = myArray.length; i < len; i++ ) { ... }
如果你想要更简洁的语法,你可以使用 forEach:
myArray.forEach( function ( val, i ) { ... } );
如果要使用此方法,请确保包含 ES5 shim 以添加对旧浏览器的支持。
rushUp给出的答案是正确的,但这会更方便
for (let [index, val] of array.entries() || []) {
// your code goes here
}
|| []
是不必要的,永远不会使用; array.entries()
总是真实的。
要在数组上使用 for..of 循环并检索索引,您可以使用 array1.indexOf(element)
它将返回循环中元素的索引值。您可以使用此方法返回索引和值。
array1 = ['a', 'b', 'c'] for (array1 的元素) { console.log(array1.indexOf(element), element) // 0 a 1 b 2 c }
正如评论中提到的,当数组包含非唯一值时,这将返回错误索引。 (考虑到 arr = ['a', 'b', 'c', 'a'],arr[3] 的索引将返回 0 而不是 3)
这是一个函数 eachWithIndex
,它适用于任何可迭代的东西。
您还可以编写一个类似的函数 eachWithKey
,使用 for...in
处理对象。
// example generator (returns an iterator that can only be iterated once)
function* eachFromTo(start, end) { for (let i = start; i <= end; i++) yield i }
// convers an iterable to an array (potential infinite loop)
function eachToArray(iterable) {
const result = []
for (const val of iterable) result.push(val)
return result
}
// yields every value and index of an iterable (array, generator, ...)
function* eachWithIndex(iterable) {
const shared = new Array(2)
shared[1] = 0
for (shared[0] of iterable) {
yield shared
shared[1]++
}
}
console.log('iterate values and indexes from a generator')
for (const [val, i] of eachWithIndex(eachFromTo(10, 13))) console.log(val, i)
console.log('create an array')
const anArray = eachToArray(eachFromTo(10, 13))
console.log(anArray)
console.log('iterate values and indexes from an array')
for (const [val, i] of eachWithIndex(anArray)) console.log(val, i)
生成器的好处是它们很懒,可以将另一个生成器的结果作为参数。
除了每个人都发布的非常好的答案之外,我想补充一点,最高效的解决方案是 ES6 entries
。对于这里的许多开发人员来说,这似乎是矛盾的,所以我创建了 this perf benchamrk。
https://i.stack.imgur.com/2WAkC.png
它快了约 6 倍。主要是因为不需要:a)多次访问数组,b)转换索引。
这是我的复合迭代器版本,它产生一个索引和任何传递的生成器函数的值,并带有一个(慢)素数搜索的例子:
const eachWithIndex = (iterable) => { return { *[Symbol.iterator]() { let i = 0 for(let val of iteratable) { i++ yield [i, val] } } } } const isPrime = (n) = > { for (i = 2; i < Math.floor(Math.sqrt(n) + 1); i++) { if (n % i == 0) { return false } } return true } let primes = { *[ Symbol.iterator]() { let Candidate = 2 while (true) { if (isPrime(candidate)) yield Candidate Candidate++ } } } for (const [i, prime] of eachWithIndex(primes)) { console.log(i,素数) if (i === 100) 中断 }
eachWithIndex[Symbol.iterator]
而不仅仅是一个函数 eachWithIndex
? eachWithIndex
不满足可迭代接口,这是 Symbol.iterator
的全部要点。
eachWithIndex
更改为接受可迭代并返回封闭的复合可迭代。
通过 js 中的 for of 循环系统,你可以找到所有索引为 no 的数组元素...
const menus = ['Bengali', 'Italiano', 'Americano', 'Thai', 'Chinese'];
for (const menus of menu.entries()) {
console.log(menus);
}
ReferenceError: menu is not defined
let
是具有块范围的var
。const
不变。%d
格式化整数,%s
格式化字符串。它们基于 printf。 console.spec.whatwg.org/#formatter 正在制定规范。