我被告知在JavaScript中不要使用for...in
循环遍历数组。为什么?
我被告知在JavaScript中不要使用for...in
循环遍历数组。为什么?
根据你的操作,这并不一定是坏事,但在数组的情况下,如果有东西被添加到Array.prototype
中,那么你会得到奇怪的结果。本来你希望循环运行三次:
var arr = ['a','b','c'];
for (var key in arr) { ... }
helpfulUtilityMethod
的函数,则您的循环将运行四次: key
会是0
、1
、2
和helpfulUtilityMethod
。如果您只期望整数,那就糟糕了。您应该仅在属性列表上使用for(var x in y)
,而不是在对象上使用(如上所述)。
for...in
循环遍历数组并不是错误的,但我可以猜测为什么有人告诉你这个:
1.) 对于数组来说,已经存在一个更高级的函数或方法,名为“forEach”,它具有更多的功能和更简洁的语法:Array.prototype.forEach(function(element, index, array) {} );
2.) 数组总是有一个长度,但是for...in
和forEach
不会执行任何值为'undefined'
的函数,只会为那些具有定义值的索引执行函数。所以,如果你只分配了一个值,这些循环只会执行一次函数,但由于数组是枚举的,它将始终具有长度,直到具有定义值的最高索引位置,但在使用这些循环时,这个长度可能被忽略。
3.) 标准的for循环将根据参数定义的次数执行函数,并且由于数组是编号的,因此更有意义的是定义要执行函数的次数。与其他循环不同,for循环可以为数组中的每个索引执行函数,无论值是否被定义。
本质上,你可以使用任何循环,但是你应该记住它们的工作方式。了解不同循环迭代的条件、它们各自的功能,并意识到它们在不同情况下更或少适用。
此外,通常使用forEach
方法而不是for...in
循环被认为是更好的实践,因为它更容易编写并具有更多的功能,因此你可能想养成只使用这种方法和标准for循环的习惯,但这取决于你自己。
如下所示,前两个循环仅执行一次console.log语句,而标准for循环根据指定的次数执行函数,在本例中,array.length = 6。
var arr = [];
arr[5] = 'F';
for (var index in arr) {
console.log(index);
console.log(arr[index]);
console.log(arr)
}
// 5
// 'F'
// => (6) [undefined x 5, 6]
arr.forEach(function(element, index, arr) {
console.log(index);
console.log(element);
console.log(arr);
});
// 5
// 'F'
// => Array (6) [undefined x 5, 6]
for (var index = 0; index < arr.length; index++) {
console.log(index);
console.log(arr[index]);
console.log(arr);
};
// 0
// undefined
// => Array (6) [undefined x 5, 6]
// 1
// undefined
// => Array (6) [undefined x 5, 6]
// 2
// undefined
// => Array (6) [undefined x 5, 6]
// 3
// undefined
// => Array (6) [undefined x 5, 6]
// 4
// undefined
// => Array (6) [undefined x 5, 6]
// 5
// 'F'
// => Array (6) [undefined x 5, 6]
for...in循环始终枚举键名。
对象属性的键名始终为字符串,即使是数组的索引属性也是如此:
var myArray = ['a', 'b', 'c', 'd'];
var total = 0
for (elem in myArray) {
total += elem
}
console.log(total); // 00123
for...in 在 JavaScript 中对于对象很有用,但对于数组则不太适用。虽然我们不能说这是错误的方式,但也不推荐使用。请看下面使用 for...in 循环的示例:
let txt = "";
const person = {fname:"Alireza", lname:"Dezfoolian", age:35};
for (const x in person) {
txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35
好的,现在让我们使用数组来完成它:
let txt = "";
const person = ["Alireza", "Dezfoolian", 35];
for (const x in person) {
txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35
正如您所看到的结果一样...
但是,让我们尝试一些东西,让我们原型化一些 Array...
Array.prototype.someoneelse = "someoneelse";
let txt = "";
const arr = new Array();
arr[0] = 'Alireza';
arr[1] = 'Dezfoolian';
arr[2] = 35;
for(x in arr) {
txt += arr[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 someoneelse
你看到了someoneelse!!!...在这种情况下,我们实际上是循环遍历新的Array对象!
因此,这就是为什么我们需要小心使用for..in的原因之一,但并不总是如此...
NodeList
一起使用(例如从querySelectorAll
调用中获取),因为它根本不会看到返回的元素,只会迭代NodeList
属性。var nodes = document.querySelectorAll(selector);
nodes
▶ NodeList [a._19eb]
for (node in nodes) {console.log(node)};
VM505:1 0
VM505:1 length
VM505:1 item
VM505:1 entries
VM505:1 forEach
VM505:1 keys
VM505:1 values
for (node in nodes) node.href = newLink;
失败了。JavaScript
确实是一门为自由的人而设计的语言,ROCK
,没有规则。起初容易,最后难。哈哈Array.prototype.foo = 1;
var a = [];
a[5] = 5;
console.log(a.length) // 6
a.map(e => console.log(e)) // 5
a.forEach(e => console.log(e)) // 5
for(let i in a) console.log(i) // 5, foo
for(let i of a) console.log(i) // undefined..., foo
在for循环中,当遍历数组时,索引会被转换为字符串。例如,在下面的代码中,在第二个循环中将j初始化为i+1时,i是索引,但是以字符串形式表示(“0”,“1”等),而在js中数字和字符串相加得到的结果也是字符串。如果js遇到“0”+1,它将返回“01”。
var maxProfit = function(prices) {
let maxProfit = 0;
for (let i in prices) {
for (let j = i + 1; j < prices.length; j++) {
console.log(prices[j] - prices[i], "i,j", i, j, typeof i, typeof j);
if ((prices[j] - prices[i]) > maxProfit) maxProfit = (prices[j] - prices[i]);
}
}
return maxProfit;
};
maxProfit([7, 1, 5, 3, 6, 4]);
var i = hCol1.length; for (i;i;i--;) {}
,将 i 缓存起来会有所不同,并简化测试。对于老版本的浏览器而言,for
和while
的差异越大,因此请始终缓存 "i" 计数器。当然,负数并不总是适用于所有情况,并且while
在某些人看来会使代码更加难懂。另外,请注意var i = 1000; for (i; i; i--) {}
和var b =1000 for (b; b--;) {}
这两种写法,其中 i 从 1000 到 1,b 从 999 到 0。对于老版本的浏览器而言,while
倾向于使用for
以提高性能。 - Mark Schultheissfor(var i = 0, l = myArray.length; i < l; ++i) ...
是使用顺序迭代时最快和最好的选择。 - Mathieu Amiot