Javascript 排序后强制数组重新计算长度
如果使用数组并执行以下操作:Javascript 排序后强制数组重新计算长度,javascript,google-chrome,Javascript,Google Chrome,如果使用数组并执行以下操作: arr = []; arr[100] = 1; 长度将为101,这是有意义的,因为0-99被设置为undefined 现在,如果我们对该数组进行排序:arr.sort()它将如下所示:[1,未定义的x100],因为键不会被保留。但是,长度仍然是101,因为未定义的已全部移到末尾,而不是移除 这种行为是故意的吗?如果是这样的话:是否有一个内置函数可以删除未定义的并重新计算,为什么是故意的 我不是问如何编写自己的函数来重新计算长度。排序数组的长度可以很容易地通过for
arr = [];
arr[100] = 1;
长度将为101,这是有意义的,因为0-99被设置为undefined
现在,如果我们对该数组进行排序:arr.sort()
它将如下所示:[1,未定义的x100]
,因为键不会被保留。但是,长度仍然是101,因为未定义的
已全部移到末尾,而不是移除
这种行为是故意的吗?如果是这样的话:是否有一个内置函数可以删除未定义的并重新计算,为什么是故意的
我不是问如何编写自己的函数来重新计算长度。排序数组的长度可以很容易地通过for(x=0;arr[x]!=undefined;x++)强制执行;arr.length=x代码>
> 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,未定义x100]
不,没有。它在0处有一个成员,长度为100。没有100个成员的值为“undefined”
如果希望将数组缩减为仅定义的成员,则没有内置函数来完成此操作(即,本质上是将长度设置为具有值的最高索引)
只能通过在数组上迭代来实现,例如,从右边开始减少长度,直到达到现有属性为止:
function trimArray(arr) {
var i = arr.length;
while ( !(--i in arr)) {
arr.length -= 1;
}
}
请注意,要使上述操作正常工作,必须对数组进行排序。此外,它还修改传入的数组
下面是一种使用压缩方法扩展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;
}
}
它将用只包含已定义成员的新数组替换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
如果需要保留原始阵列,这可能是有用的行为。相反,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
或类似名称,以避免与未来版本发生意外冲突,并使其明显表明它是本机方法,不是内置的
我也有点难以找到一个合适的名称,因为packed和compressed已经定义了不同于non-continuous的含义,但这似乎很难理解,所以现在它是compressed。如果您想解决这个问题,请在对数组进行排序(或在排序之前对其进行过滤)后立即使用它
实际发生的是,您正在重写length
属性,该属性由Array
对象用于确定数组的结尾位置,以及数组是否有那么多属性
arr = [];
arr[100] = 1;
代码不会将0-99
设置为undefined
,它只会将键100
设置为1
,将length
属性设置为101
和Array.sort
不会更改数组的属性length
排序后,有两个自己的属性arr
,0
是1
,length
仍然是101
为什么排序会删除元素?@DaveNewton因为排序承认元素没有定义,为什么要保留它们?排序后是否可以应用其他函数来删除它们?如果您有一个给定长度的数组,并对其进行排序,我不理解如果长度不同,则返回一些内容的想法。@Rhyono最后的函数将删除值为null
和未定义的成员(即,它们的值为undefined
)。我使用的是Chrome(根据标签)和开发者控制台:以下是数组[1,10,10,2,undefined×96]
@Rhyono的确切输出,这是由于开发者控制台显示数组数据的方式。如果使用arr.hasOwnProperty(10)
您应该得到false
,因为它实际上没有设置该属性。@Rhyono记住,JavaScript中的“数组”与Java或C中的数组不同。@zzzzBov这就是我要找的。这也是我特别说“chrome”的原因在标记中,因为它实际上没有意义将所有这些定义为未定义的,但因为它只是它表示它的方式:这是可以理解的。@Rhyono,firefox中的firebug还显示了许多未定义的列表,因为未设置的属性将返回未定义的(例如a={};a[100];//未定义的)。这不是OP要求的。他们声明他们已经知道如何执行上述操作。@zzzzBov函数应该是var y=x.filter(函数(项){return item;});
因为只访问存在的成员。您的函数将删除值为未定义的现有成员@RobG,不确定您引用的是什么API,但是。如果使用返回项;
,将从数组中删除假值。@zzzzBov是的,您是对的。筛选函数应返回真值代码>以便保留所有已定义的属性(包括那些具有虚假值的属性,例如未定义的
,虚假的
,0
,等等)。如果长度不超过100,则表示它的方式会有所不同。这让我很反感。
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
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
var arr;
arr = [];
arr[100] = 1;
arr.sort();
arr = arr.filter(function (item) {
return typeof item !== 'undefined';
});
arr = [];
arr[100] = 1;