简体   繁体   English

JavaScript中for循环和for-in循环之间的区别

[英]difference between for loop and for-in loop in javascript

I found that there is a difference between for loop and for-in loop in javascript. 我发现javascript中的for循环和for-in循环之间有区别。

When I define a new array: 当我定义一个新数组时:

var a=new Array();

Then I put some value into in but not contiguously for example: 然后例如但不连续地添加一些值:

a[0]=0;a[1]=1;a[4]=4; 

When I use for(i=0;i<5;i++) to get the value and use alert to show it, it's different from using for(i in a) . 当我使用for(i=0;i<5;i++)获取值并使用alert显示它时,它与使用for(i in a)

The previous one will show elements in index 2,3 which shows "undefined" while for-in will show only index 0,1,and 4. Can anybody tell me why? 前一个将显示索引2,3中的元素,该元素显示“未定义”,而for-in将仅显示索引0,1和4。有人可以告诉我为什么吗?

For loop iterates over them until the i reaches to 5 so i = 0,1,2,3,4,5 and iterates over all. For循环遍历它们,直到i达到5,因此i = 0、1、2、3、4、5并遍历所有。 But with for...in loop iterates over their properties only not 0 to 5 but 0,1,4 that you've defined. 但是,使用for ... in循环仅迭代其属性,而不是0到5,而是您定义的0,1,4。

From MDN : MDN

Note: for..in should not be used to iterate over an Array where index order is important. 注意: for..in不应用于遍历索引顺序很重要的Array。

Array indexes are just enumerable properties with integer names and are otherwise identical to general Object properties. 数组索引只是具有整数名称的可枚举属性,其他方面与常规Object属性相同。 There is no guarantee that for...in will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited. 无法保证for ... in将以任何特定顺序返回索引,并且将返回所有可枚举的属性,包括具有非整数名称的属性和被继承的属性。

Because the order of iteration is implementation dependent, iterating over an array may not visit elements in a consistent order. 因为迭代的顺序取决于实现,所以在数组上进行迭代可能不会以一致的顺序访问元素。 Therefore it is better to use a for loop with a numeric index (or Array.forEach or the for...of loop) when iterating over arrays where the order of access is important. 因此,在访问顺序很重要的数组上进行迭代时,最好使用带有数字索引的for循环(或Array.forEach或for ... of循环)。

for (... in ...) is typically used to iterate through the properties of objects (which are what javaScript uses for associative arrays), while the typical for loop is used for sequential arrays. for (... in ...)通常用于遍历对象的属性(这是javaScript用于关联数组的属性),而典型的for循环用于顺序数组。

In your example, you are really creating an associative array with the keys 0, 1, and 4. If you wanted a true javaScript array, you'd use a.push(0) , a.push(1) , etc... in order to add the values, sequentially , onto the end of the array. 在您的示例中,您实际上是在用键0、1和4创建一个关联数组。如果要使用真正的javaScript数组,则可以使用a.push(0)a.push(1)等。 。为了添加值, 顺序地 ,在阵列上的端部。

With a sequential array, the syntax for (var i = 0; i < arr.length; i++) makes i count from 0 to 1 less than the length of the array. 对于顺序数组,语法for (var i = 0; i < arr.length; i++)使i计数从0到1小于数组的长度。 This will allow i to be equal to each index in the array, one-by-one, allowing you to access each element in that array. 这将使i一一等于数组中的每个索引,从而允许您访问该数组中的每个元素。

With associative arrays, however, the keys are non-sequential, so making a variable count 'from 0 to 1 less than the length of the array' won't produce the desired results. 但是,对于关联数组,键是非顺序键,因此使变量计数“比数组长度小0到1”将不会产生期望的结果。 In your example it is close to working because your manually created keys just happen to be 0, 1, and 4, which are almost sequential. 在您的示例中,由于您手动创建的键恰好是0、1和4(几乎是连续的),因此已接近正常工作。

If you want to have an array with non-sequential keys--'non-contiguous' as in 0, 1, 4, etc..--you should probably use objects, not arrays, eg 如果您想要一个带有非顺序键的数组(例如“ 0”,“ 1”,“ 4”等“非连续”键),则应该使用对象而不是数组,例如

var obj = {};
obj[0] = 0;
obj[1] = 1;
obj[4] = 4;

And then using the for (... in ...) loop would be the correct syntax. 然后使用for (... in ...)循环将是正确的语法。

for-in loop enumerates on the enumerable properties of a variable. for-in循环枚举变量的可枚举属性。 For your array, "0", "1" and "4" are added as enumerable property on the array. 对于您的数组,将“ 0”,“ 1”和“ 4”作为可枚举属性添加到数组中。 Therefore, for-in loop only gets 0, 1 and 4 in "i". 因此,for-in循环在“ i”中仅获得0、1和4。

for loop works with the i = 0 to 5. so you try to access values at 2 and 3 as well which obviously are undefined. for循环适用于i = 0至5。因此,您也尝试访问2和3处的值,这些值显然是未定义的。

The syntax 语法

for (var k in obj)

is actually a for-each loop. 实际上是一个for-each循环。 It iterates through the properties of an object. 它遍历对象的属性。 You should familiarize yourself with JavaScript objects. 您应该熟悉JavaScript对象。 An object is map of keys to values. 对象是键到值的映射。

So, the for-each loop can be very useful with objects. 因此,for-each循环对对象非常有用。 But, when looping through an array, it's better to use a regular for loop. 但是,在遍历数组时,最好使用常规的for循环。

Here is an example of a for-each loop used on the properties of an object: http://jsfiddle.net/nbtLpw0z/ . 这是在对象的属性上使用的for-each循环的示例: http : //jsfiddle.net/nbtLpw0z/

I am useing for-in loop because it is a shorter form, but sometimes you may want to have control over the iteration variable. 我使用的是for-in循环,因为它是一种较短的形式,但是有时您可能希望控制迭代变量。 For instance, if you want to iterate over even indices, you'd need to use the normal for loop: 例如,如果要遍历偶数索引,则需要使用常规的for循环:

for (var i = 0; i < myarray.length; i+=1) {...}

The same applies, for example, if you want to iterate backwards: 例如,如果要向后迭代,则同样适用:

for (var i = myarray.length-1; i >= 0; i--) {...}

Certainly, for objects, the for-in loop allows you to get the property name in the iteration variable.for ex. 当然,对于对象,for-in循环允许您在迭代变量中获取属性名称。

 var obj = {year: 2014, city: "Surat"}
 for (var propn in obj) alert(propn + " = " + obj[propn]);

In your example, I'd use for-in because you are doing a simple iteration. 在您的示例中,我将使用for-in,因为您正在执行简单的迭代。 Moreover I think in a non-optimized Javascript compiler/interpreter, the for-in loop would be even faster because variable increment is done internally. 而且我认为在未优化的Javascript编译器/解释器中,for-in循环会更快,因为变量增量是在内部完成的。

For starters there is no point is using a for in loop on an Array because arrays in JavaScript can only have ordered, numeric indexes. 对于初学者来说for in Array上使用for in循环是没有意义的for in因为JavaScript中的数组只能具有有序的数字索引。 So you can access the array at any index between the range of 0 and array.length - 1 Alas, if you wanted to use a for in loop to iterate over an array you certainly can, however, a regular for loop is more appropriate. 因此,您可以在0array.length - 1之间的任何索引处访问数组,如果您想使用for in循环遍历数组,您当然可以,但是,常规的for循环更合适。

A for in loop is used when you don't have ordered numeric indices. 如果您没有订购数字索引,则使用for in循环。 JavaScript objects are really an ordered hash table. JavaScript对象实际上是一个有序哈希表。 You can access keys of JavaScript objects with the in operator which returns the key for the object, and by accessing the object at that key you can get the value. 您可以使用in操作符访问JavaScript对象的键,该操作符返回对象的键,并通过访问该键的对象来获取值。

For example: 例如:

var obj = {
   hello: "world",
   world: "hello"
};

A regular for loop wouldn't work, so you would need t use a for in loop. 常规的for循环不起作用,因此您无需使用for in循环。

for(var i in obj) console.log(obj[i]);

Objects also don't return a length property that is accurate enough to iterate over the entire object, so a for in loop is absolutely necessary. 对象也不会返回足够准确的length属性以迭代整个对象,因此for in循环是绝对必要的。

Also note that by assigning values to the array not in the order in which the next free element would exist will automatically place undefined in the elements that you skipped. 还要注意,通过不按下一个空闲元素的存在顺序为数组分配值,将自动在您跳过的元素中放置undefined

In your example, the array would look like this: 在您的示例中,数组如下所示:

[0, 1, undefined × 2, 4]

for-each loop is recommended for traversing object properties, whereas for loop is recommended for arrays. for-each环被推荐用于遍历对象属性,而for循环被推荐用于阵列。 In your case you can use push() to get same results. 您可以使用push()获得相同的结果。

 var a = []; //recommended way of declaring arrays over `new Arrays()` a.push(0); a.push(1); a.push(4); //usual for-loop for (var i = 0; a.length > i; i++) //recommended console.log('a[', i, ']=', a[i]); console.log('---------------------'); // for-each loop for (var k in a) //not recommended console.log('a[', k, ']=', a[k]); console.log('---------------------'); 
 Open console... 

 var person = { 'name': 'Adam' }; for (var k in person) console.log('person.' + k, '=', person[k]); console.log('----------------------'); person.age = 26; //new property for (var k in person) console.log('person.' + k, '=', person[k]); console.log('----------------------'); person['gender'] = 'Male'; //again a new property for (var k in person) console.log('person.' + k, '=', person[k]); console.log('----------------------'); person.name = 'Will'; //updating property for (var k in person) console.log('person.' + k, '=', person[k]); console.log('----------------------'); 
 Open console... 

Under the hood the for-in loop is nothing but a for loop. 在幕后,for-in循环不过是for循环。 For(i in x) is broken down in to - For(i in x)分解为-

for(i=0;i<x.length;i++) {
if(x[i] != undefined)
console.log(x[i]);
}

I've read and heard that normal for loops: for(var i = 0; i < arr.length; i++) is faster. 我已经阅读并听到了正常的for循环: for(var i = 0; i < arr.length; i++)更快。 But I'd say use for of : 但是我会说for of使用:

var arr = [1,2,3], obj = {x: 1, y:2};
for(var value of arr) console.log(value) // 1, 2, 3
for(var key in obj) console.log(key) // x, y
for(var key of Object.keys(obj)) console.log(key) // x, y

you can use Object.keys(obj) to convert the object's keys to an array and call Array.prototype methods on it 您可以使用Object.keys(obj)将对象的键转换为数组,并在其上调用Array.prototype方法

Your "for" loop looks at all the values of the indices of the array from 0-4, as that is exactly what you are asking it to do. 您的“ for”循环从0-4开始查看数组索引的所有值,因为这正是您要执行的操作。 So it takes a look at a[0] and finds a value, then a[1] (same deal), then it goes to a[2] and realizes that you never initialized a value for a[2], therefore it's undefined. 因此,它先查看a [0]并找到一个值,然后找到a [1](相同的交易),然后转到a [2]并意识到您从未为a [2]初始化一个值,因此未定义。 Same goes for a[3], and finally a[4] has a value so it finds it. a [3]也是一样,最后a [4]具有一个值,以便找到它。

That type of "for" loop will check every index whether defined or not. 这种“ for”循环的类型将检查每个索引是否已定义。

A "for ... in ..." loop will only check initialized values. “ for ... in ...”循环将仅检查初始化值。 Your array has 3 values that have been initialized, therefore it checks those. 您的数组具有3个已初始化的值,因此它将检查这些值。 It will show them to you in the order of their indices, but the indices don't actually affect what it's looking at. 它将按照索引的顺序向您显示,但是索引实际上并不会影响它的外观。 So if you changed your "a[1]" to "a[3]" and "a[4]" to "a[10]", you'd still get the exact same answer when you use a "for ... in ..." loop. 因此,如果将“ a [1]”更改为“ a [3]”,将“ a [4]”更改为“ a [10]”,则将“。”使用时仍会得到完全相同的答案。 。in ...”循环中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM