我被告知不要使用。。。在JavaScript中使用数组。为什么不呢?
当前回答
for in循环在遍历数组时将索引转换为字符串。例如,在下面的代码中,在用i+1初始化j的第二个循环中,i是索引,但在字符串(“0”、“1”等)中,js中的number+string是字符串。如果js遇到“0”+1,则返回“01”。
var maxProfit=函数(价格){设maxProfit=0;for(让我输入价格){for(设j=i+1;j<prices.length;j++){console.log(价格[j]-价格[i],“i,j”,i,j,类型i,类型j);如果((prices[j]-prices[i])>maxProfit)maxProfit=(prices[j]-prices[i]);}}return maxProfit;};最大利润([7,1,5,3,6,4]);
其他回答
因为。。。in通过持有数组的对象枚举,而不是数组本身。如果我向数组原型链中添加了一个函数,那么它也将包含在内。即。
Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
document.write(x + ' = ' + a[x]);
}
这将写入:
0 = foo 1 = bar myOwnFunction = function() { alert(this); }
而且,由于您永远无法确定不会向原型链中添加任何内容,因此只需使用for循环来枚举数组:
for(i=0,x=a.length;i<x;i++){
document.write(i + ' = ' + a[i]);
}
这将写入:
0 = foo 1 = bar
此外,由于语义的原因,在treats数组(即与任何其他JavaScript对象相同)中使用的方法与其他流行语言不一致。
// C#
char[] a = new char[] {'A', 'B', 'C'};
foreach (char x in a) System.Console.Write(x); //Output: "ABC"
// Java
char[] a = {'A', 'B', 'C'};
for (char x : a) System.out.print(x); //Output: "ABC"
// PHP
$a = array('A', 'B', 'C');
foreach ($a as $x) echo $x; //Output: "ABC"
// JavaScript
var a = ['A', 'B', 'C'];
for (var x in a) document.write(x); //Output: "012"
因为如果你不小心的话,它会迭代属于原型链上对象的财产。
您可以使用。。在中,只需确保使用hasOwnProperty检查每个属性。
孤立地说,在数组中使用for没有错。For-in迭代对象的属性名,在“现成”数组的情况下,财产对应于数组索引。(像length、toString等内置属性不包含在迭代中。)
然而,如果您的代码(或您正在使用的框架)将自定义财产添加到数组或数组原型中,那么这些财产将包含在迭代中,这可能不是您想要的。
一些JS框架,如Prototype修改了Array原型。像JQuery这样的其他框架则不然,因此使用JQuery,您可以在中安全地使用。
如果你有疑问,你可能不应该使用。
迭代数组的另一种方法是使用for循环:
for (var ix=0;ix<arr.length;ix++) alert(ix);
然而,这有一个不同的问题。问题是JavaScript数组可能有“洞”。如果您将arr定义为:
var arr = ["hello"];
arr[100] = "goodbye";
然后数组有两个项目,但长度为101。在中使用for将产生两个索引,而for循环将产生101个索引,其中99的值为undefined。
的问题。。。在…-只有当程序员不真正理解语言时,这才成为问题;它实际上不是一个bug或任何东西,而是它迭代对象的所有成员(好吧,所有可枚举成员,但这只是一个细节)。当您只想迭代数组的索引财产时,确保语义一致的唯一方法是使用整数索引(即for(vari=0;i<array.length;++i)样式循环)。
任何对象都可以有与之关联的任意财产。特别是将附加财产加载到数组实例上并没有什么可怕的。如果代码只想看到索引的类似数组的财产,则必须坚持使用整数索引。完全了解用于…的代码。。。在does和really需要查看所有财产,那么这也没关系。