Array.length给出了不正确的长度

时间:2015-06-26 04:42:15

标签: javascript arrays

如果我有一个数组,其对象作为索引的值,如:

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
alert(a.length); // outputs 91

我找到了解决方法来获取实际长度:

function getLength(arr) {
    return Object.keys(arr).length;
}
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
alert(getLength(a));

但是,当对象以随机索引存储时,为什么JS会给出不正确的长度?它只是在数组中找到的最大索引加1。与上面的例子一样,90是最大的指数。它只增加1并输出91。 Demonstration

4 个答案:

答案 0 :(得分:10)

这是因为length为您提供了阵列中可用的下一个index

DOCS

<强> arrayLength

  

如果传递给Array构造函数的唯一参数是0到2 ^ 32-1(含)之间的整数,则返回一个长度设置为该数字的新JavaScript数组。

ECMA Specifications

由于您没有在21,90,13之外的其他键中插入任何元素,因此所有其余索引都包含undefinedDEMO

获取数组中的实际元素数:

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};

var len = 0;

for (var i = 0; i < a.length; i++) {
  if (a[i] !== undefined) {
    len++;
  }
}
document.write(len);

更短的版本

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};


for (var i = 0, len = 0; i < a.length; i++, a[i] !== undefined && len++);


document.write(len);

DEMO

修改

如果数组包含大量元素,则循环获取其长度不是最佳选择。

正如您在问题中提到的, Object.keys(arr).length 是这种情况下的最佳解决方案,因为您没有在该阵列上添加任何属性。否则,length将不会是您所期望的。(感谢@RobG)

答案 1 :(得分:4)

因为这是ECMAScript spec中描述的Array.length的行为。

  

此Array对象的length属性是一个data属性,其值始终在数值上大于名称为数组索引的每个deletable属性的名称。

因此,Array.length始终是最后一项的索引+ 1。

答案 2 :(得分:4)

JavaScript中的数组是一个简单的从零开始的结构。 if返回array.length,其中n + 1是数组中的最大索引。

它是如何工作的 - 当你分配第90个元素并且这个数组的长度小于90时,它会将数组扩展为90并设置第90个元素&#39 ; s值。所有缺失值都被解释为n

如果您尝试以下代码:

null

您将获得以下JSON:

  

[NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,{},NULL,NULL,NULL,NULL,NULL,NULL,NULL,{}, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,{}]

此外,var a = []; a[21] = {}; a[90] = {}; a[13] = {}; console.log(JSON.stringify(a)); 不是只读值 如果您设置的array.length小于,那么数组将调整大小:

length

如果您设置的 var arr = [1,2,3,4,5]; arr.length = 3; console.log(JSON.stringify(arr)); // [1,2,3] 更多,那么该阵列也将展开:

length

如果您需要分配这些值,可以使用JS对象 您可以将它们用作关联数组并分配任何键值对。

 var arr = [1,2,3];
 arr.length = 5;
 console.log(JSON.stringify(arr));
 // [1,2,3,null,null]

答案 3 :(得分:0)

这是因为你有一个[90]最大的索引,所以索引从0到90开始变为91。

如果你没有像[80]等那样传递值,javascript会将它们存储为孔,例如[1, , 3, , ,90],其中使用逗号表示数组中的孔。

如果您尝试访问这些值,那么您将获得undefined