如果你拿一个数组并执行以下操作:
arr = [];
arr[100] = 1;
长度为101,由于0-99被设置为undefined
现在,如果我们对该数组进行排序:arr.sort()
它将如下所示:[1, undefined x100]
因为不保留密钥。但是,长度仍然是101,因为undefined
已全部移动到最后,而不是移除。
这种行为是否是故意的,如果是这样的话:是否有内置函数删除undefined
并重新计算,为什么有意?
我不询问如何编写我自己的函数来重新计算长度。使用for (x = 0; arr[x] != undefined; x++);arr.length = x;
答案 0 :(得分:5)
> arr = [];
> arr[100] = 1;
> The length will be 101, which makes sense due to 0-99 being set as undefined
数组在100处只有一个成员,它就像:
var arr = { '100': 1, 'length': 101};
现在,如果我们对该数组进行排序:arr.sort()它将如下所示:[1,undefined x100]
不,它没有。它有一个成员为0,长度为100.没有100个成员的值为'undefined'。
如果您希望将数组简化为仅定义的成员,则没有内置函数来执行此操作(即基本上将 length 设置为具有值的最高索引)。
你只能通过迭代数组来做到这一点,例如通过减少从右边到现有属性的长度:
function trimArray(arr) {
var i = arr.length;
while ( !(--i in arr)) {
arr.length -= 1;
}
}
请注意,要使上述方法正常工作,必须对数组进行排序。此外,它还会修改传入的数组。
这是一种使用compress方法扩展Array.prototype的方法,因此只存在已定义成员的数组,并且适当地重置了长度:
if (!('compress' in Array.prototype)) {
Array.prototype.compress = function() {
var i = 0,
lastExisting = 0,
len = this.length;
do {
if (i in this) {
this[lastExisting++] = this[i];
}
} while (++i < len)
this.length = lastExisting;
}
}
请注意,它不会删除值 undefined 的成员,只会删除那些根本不存在的成员。所以:
var x = [,,,,1,,,2];
x[20] = void 0;
x.compress()
alert(x + '\n' + x.length); // [1,2,<undefined>], length = 3
正如zzzzBov所指出的,这也可以使用filter
:
var x = x.filter(function(item){return true;});
将使用仅包含已定义成员的新数组替换x
,无论其值如何。它将是非稀疏的(或连续的)并具有适当的长度,例如
var x = [,,,,1,,,2];
x[20] = void 0; // set x[20] to undefined, length is 21
x = x.filter(function(item){return true;}); // [2, 3, <undefined>], length = 3
请注意,此方法仅更新x引用的数组,不会更新对同一数组的任何其他引用,例如
var x = [,,1];
var y = x; // x and y reference same array
x = x.filter(function(item){return true}); // x is now another array of members
// filtered from the original array
alert(x); // [1] x references a different array
alert(y); // [,,1] y still references the original array
如果需要保留原始数组,这可能是有用的行为。相反,compress
方法修改原始数组:
var x = [,,1];
var y = x; // x and y reference same array
x.compress();
alert(x); // [1] x is a modified version of the original array
alert(y); // [1] y references the same (original) array
我不知道是否有意在未来版本的ECMAScript中将这种方法添加到Array.prototype
或者它可能被调用的内容,因此可能建议使用其他名称,例如xcompress
或类似的,以避免与未来版本的意外冲突,并明确表明它是一种本机方法,而非内置方法。
我也有点难以找到合适的名字,因为压缩和压缩已经定义了与非连续,但这看起来很笨重,所以现在压缩。
答案 1 :(得分:1)
arr = [];
arr[100] = 1;
代码不会将0-99
设置为undefined
,它只将密钥100
设置为1
,将length
属性设置为{ {1}}。
并且101
不会更改数组的属性Array.sort
。
排序后,length
有两个属性,arr
为0
,1
仍为length
。
答案 2 :(得分:0)
如果您想要解决问题,请在对数组进行排序后对其进行filter
(或在排序之前对其进行过滤)。
var arr;
arr = [];
arr[100] = 1;
arr.sort();
arr = arr.filter(function (item) {
return typeof item !== 'undefined';
});
实际发生的是你正在覆盖length
属性,Array
对象使用该属性来确定数组末尾的位置,数组是否具有那么多属性