Javascript Array.length提供的长度不正确

Javascript Array.length提供的长度不正确,javascript,arrays,Javascript,Arrays,如果我有一个数组,其索引处的值为object,如下所示: 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(getL

如果我有一个数组,其索引处的值为object,如下所示:

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作为输出

这是因为提供了数组中可用的下一个
索引

阵列长度

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

因为除了21、90、13之外,您没有在其他键中插入任何元素,所以所有剩余的索引都包含
未定义的

要获取数组中的实际元素数,请执行以下操作:

var a=[];
a[21]={};
a[90]={};
a[13]={};
var-len=0;
对于(变量i=0;i文件。书写(len)这是因为您有一个[90]作为最大索引,所以索引从0到90的长度变为91

如果没有传递值,如[80]等,javascript会将它们存储为孔,即对于eg
[1,3,90]
,其中使用逗号表示数组中的孔


如果尝试访问这些值,则会得到未定义的

,因为这是Array.length的行为,如中所述

此数组对象的length属性是一个数据属性,其值在数值上始终大于名称为数组索引的每个可删除属性的名称


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

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

这就是它的工作原理-当您指定第90个元素且该数组的长度小于90时,它会将数组扩展到90并设置第90个元素的值。所有缺少的值都被解释为
null

如果您尝试以下代码:

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
console.log(JSON.stringify(a));
您将获得以下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,null,{}]

此外,
array.length
不是只读值。
如果设置的
长度
值小于当前值,则数组大小将调整为:

 var arr = [1,2,3,4,5];
 arr.length = 3;
 console.log(JSON.stringify(arr));
 // [1,2,3]
如果设置的
length
值大于当前值,则数组也将展开:

 var arr = [1,2,3];
 arr.length = 5;
 console.log(JSON.stringify(arr));
 // [1,2,3,null,null]
如果需要分配这些值,可以使用JS对象。
可以将它们用作关联数组并指定任意键值对

var a = {};
a[21] = 'a';
a[90] = 'b';
a[13] = 'c';
a['stringkey'] = 'd';
a.stringparam = 'e'; // btw, a['stringkey'] and a.stringkey is the same

console.log(JSON.stringify(a)); 
// returns {"13":"c","21":"a","90":"b","stringkey":"d","stringparam":"e"}

console.log(Object.keys(a).length);
// returns 5

您描述的行为是官方规范中定义的。问题是:为什么您对
.length
有错误的假设?想象一下
.length
返回
3
并尝试使用
for
循环来获取值。你永远也得不到价值观…@CoryDanielson,谢谢。不知道这样的官方规范存在!“我现在会一直提到它。”费利克斯克林不明白你说的话。我不擅长英语:P我需要这样的索引,因为它们在我的脚本中促进了很多。我想为
.length
找到一个补丁会很好。其他一切都很好。@CoryDanielson它在下面。谢谢。我现在明白了。但是,如果我有
a[2020]={}
?我认为在整个阵列中循环不是很好。我现在会坚持我的方法,直到其他人想出更好的解决方案。IDK Object.keys的速度有多快,但至少要比loop快。Object.keys将返回所有自己的属性,这些属性可能不都是索引。@RobG您能解释一下,这在array@Tushar-
var a=[];a、 foo=‘foo’。现在
a.length
是0,但是
Object.keys(a).length
是1。@RobG谢谢你的解释。但是,我不认为OP会这么做。只是想一想,我明白了。您建议使用JS对象,但我如何模拟与数组相同的行为?只需提供索引并获取一个值。顺便说一句,“缺失”值不会“解释为null”(并且脚本控制台不会以这种方式报告它们)。访问缺少的成员返回未定义的,与访问任何对象的不存在属性完全相同。一个成员只有在被赋值的情况下才有空值,在这种情况下它不是“丢失的”。-)