有没有一种方法可以清空一个数组,如果可以的话可能使用 .remove()
?
例如,
A = [1,2,3,4];
我该如何清空它?
有没有一种方法可以清空一个数组,如果可以的话可能使用 .remove()
?
例如,
A = [1,2,3,4];
我该如何清空它?
清空一个已存在的数组 A
的方法:
方法1
(这是我对问题最初的回答)
A = [];
A
设置为一个新的空数组。如果你没有在其他地方引用原始数组A
,那么这是完美的,因为它实际上创建了一个全新的(空)数组。但是,如果你从另一个变量或属性引用了这个数组,那么原始数组将保持不变,所以你应该小心使用这种方法,只有当你只通过原始变量A
引用该数组时才使用。var arr1 = ['a','b','c','d','e','f'];
var arr2 = arr1; // Reference arr1 by another variable
arr1 = [];
console.log(arr2); // Output ['a','b','c','d','e','f']
方法2(由Matthew Crumley建议,如建议)
A.length = 0
A.splice(0,A.length)
.splice()
函数可以完美解决问题,但由于该函数会返回一个包含所有已删除项的数组,实际上它将返回原始数组的副本。基准测试表明,这对性能没有任何影响。
方法4(由tanguy_k建议,如suggested)while(A.length > 0) {
A.pop();
}
这种解决方法不太简洁,而且与原始答案中引用的早期基准相反,是最慢的解决方法。
性能
在所有清除现有数组的方法中,方法2和方法3的性能非常相似,并且比方法4要快得多。请参见benchmark。
如Diadistis在下面的answer中指出的那样,用于确定上述四种方法性能的原始基准存在缺陷。原始基准重复使用已清除的数组,因此第二次迭代清除的是已经为空的数组。
以下基准修复了这个缺陷:http://jsben.ch/#/hyj65。它清楚地显示方法#2(长度属性)和方法#3(splice)是最快的(不计算不改变原始数组的方法#1)。
这是一个热门话题,引起了很多争议。实际上有许多正确的答案,因为这个答案已经被标记为接受的答案很长时间了,所以我会在这里列出所有的方法。
while (A.length) { A.pop(); }
的翻译是:当A数组有元素时,不断从尾部弹出元素直到数组为空。不需要加上 > 0
的条件判断。 - Ivan Blacka
之后,b
仍然持有对旧数组的引用。c
和d
仍然引用同一个数组。因此,输出结果的差异是可以预料的。 - shovavnikwhile(A.pop())
。举个例子,当 A = [2, 1, 0, -1, -2] 时,会使 A 变为 [2, 1]。即使使用 while(A.pop() !== undefined)
也不行,因为数组中可能有一个值为 undefined。这可能是编译器没有优化它的原因。 - jgawrych如果您需要保留原始数组,因为您还有其他引用它的地方需要更新,那么您可以通过将其长度设置为零来清除它,而无需创建新的数组:
A.length = 0;
length
仍然是一个特殊的属性,但它并非只读属性,因此它仍然可以工作。 - Matthew Crumley这里是最快的实现方式,同时保留相同的数组(“可变”):
function clearArray(array) {
while (array.length > 0) {
array.pop();
}
}
while (array.pop())
:测试会失败。clear()
方法,因此对于 Array 也应该有 clear()
方法才更合理。function clearArray<T>(array: T[]) {
while (array.length > 0) {
array.pop();
}
}
相应的测试:
describe('clearArray()', () => {
test('clear regular array', () => {
const array = [1, 2, 3, 4, 5];
clearArray(array);
expect(array.length).toEqual(0);
expect(array[0]).toEqual(undefined);
expect(array[4]).toEqual(undefined);
});
test('clear array that contains undefined and null', () => {
const array = [1, undefined, 3, null, 5];
clearArray(array);
expect(array.length).toEqual(0);
expect(array[0]).toEqual(undefined);
expect(array[4]).toEqual(undefined);
});
});
这里是更新后的jsPerf:http://jsperf.com/array-destroy/32 http://jsperf.com/array-destroy/152
jsPerf离线了。类似的基准测试:https://jsben.ch/hyj65
Array.prototype
,并且它正在做一些略微不同的事情,那么在你的整个代码中 [].clear()
就会稍微出错。这将不是一个愉快的调试过程。因此,总体信息是:不要修改全局变量。 - jpillorafunction clear(arr) { while(arr.length) arr.pop(); }
,然后使用 clear(arr)
而不是 arr.clear()
来清除数组。 - jpillora.splice()
和.length=0
慢得多。基准测试结果不正确。请查看我的更新答案。 - Philippe Leybaertsplice
方法清空数组A的内容:
A.splice(0, A.length);
splice
修改了数组并返回被删除的元素。首先要阅读文档:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice - David HellsingA.splice(0, A.length),0;
。这将使返回值为0
,就像A.length = 0;
一样。仍会创建生成的数组并_可能_导致脚本运行变慢:([jsperf](http://jsperf.com/clear-an-array)慢了约56%)。浏览器实现会影响它,尽管我看不出为什么“splice”比设置“length”更快。 - Evan KennedyA.splice(0)
也可以。 - corwin.amber截至目前为止,没有少于2739个赞的答案都是误导性和不正确的。
问题是:“如何清空现有数组?”例如对于A = [1,2,3,4]
。
说“A = []
是答案”是无知和完全不正确的。[] == []
是错误的。
这是因为这两个数组是两个单独的对象,有它们自己的两个身份,在数字世界中占据自己的空间,各自存在。
假设您的母亲要求您清空垃圾桶。
A = [1,2,3,4]; A = [];
一样将填充桶上的标签“A”取下并粘贴到新桶中。清空数组对象是最简单的事情:
A.length = 0;
这样,位于“A”下面的垃圾桶不仅是空的,而且干净得像新的一样!
此外,您无需在桶未清空之前手动清除垃圾!您只需要在一个回合内完全清空现有垃圾桶,而不是在桶未清空之前清理垃圾,例如:
while(A.length > 0) {
A.pop();
}
同时,将左手放在垃圾桶底部,用右手握住顶部以便拉出其中的内容,如下图所示:
A.splice(0, A.length);
不,你被要求将它清空:
A.length = 0;
这是唯一正确地清空给定JavaScript数组内容的代码。
A.length = 0
就是基本语法。虽然可能有些含糊不清,但 A.length = 0
是清空数组的标准语法。如果你想要一个 A.clear
这样的方法,你可以使用这个标准语法轻松地将其添加到你的数组中:Array.prototype.clear = function(){this.length = 0}
。玩得开心! - Bekim Bacaj性能测试:
http://jsperf.com/array-clear-methods/3
(说明:此页面是一个关于清空数组的方法性能测试的网页链接)a = []; // 37% slower
a.length = 0; // 89% slower
a.splice(0, a.length) // 97% slower
while (a.length > 0) {
a.pop();
} // Fastest
Array.prototype.clear = function() {
this.splice(0, this.length);
};
然后你可以像这样使用它:
var list = [1, 2, 3];
list.clear();
或者如果您想确保不会破坏任何东西:
if (!Array.prototype.clear) {
Array.prototype.clear = function() {
this.splice(0, this.length);
};
}
很多人认为你不应该修改原生对象(例如数组),我倾向于同意。在决定如何处理时,请谨慎使用。
您可以轻松创建一个函数来为您执行此操作,更改长度甚至将其添加到本机数组中作为可重用的remove()
函数。
想象一下您有这个数组:
var arr = [1, 2, 3, 4, 5]; //the array
好的,只需简单地运行这个命令:
arr.length = 0; //change the length
结果如下:
[] //result
清空数组的简单方法...
另外还有一种使用循环的方式,虽然不是必要的,但这也是另一种做法:
/* could be arr.pop() or arr.splice(0)
don't need to return as main array get changed */
function remove(arr) {
while(arr.length) {
arr.shift();
}
}
还有一些你可以考虑的巧妙方法,例如像这样:
arr.splice(0, arr.length); //[]
如果 arr 数组有 5 个项目,则它将从索引 0 开始剪切 5 个项目,这意味着数组中不会再剩下任何内容。
还有其他方法,比如简单地重新分配数组,例如:
arr = []; //[]
如果你看一下数组函数,还有很多其他的方法可以做到这一点,但最推荐的方法可能是改变数组的长度。
正如我在第一个位置所说的那样,你也可以原型化remove(),因为它就是你问题的答案。你可以简单地选择上述方法之一,并将其原型化到JavaScript中的Array对象,类似于:
Array.prototype.remove = Array.prototype.remove || function() {
this.splice(0, this.length);
};
arr.remove(); //[]
如果您正在使用
a = [];
那么你正在将新的数组引用分配给a,如果a中的引用已经分配给任何其他变量,则它也不会清空该数组,因此垃圾收集器不会收集该内存。
例如:
var a=[1,2,3];
var b=a;
a=[];
console.log(b);// It will print [1,2,3];
或者a.length = 0;
当我们指定a.length
时,只是重新设置了数组的范围,其余数组元素的内存将由垃圾收集器连接。
这两种解决方案更好。
a.splice(0,a.length)
和
while(a.length > 0) {
a.pop();
}
根据kenshou.html之前的回答,第二种方法更快。
a.length
上错误之外,我不认为这个新答案在主题讨论中添加了什么内容? - Bergia.length=0;
时会创建一个新的数组?对于a.length=500;
和a.length=4;
,这些引擎会如何处理? - joeytwiddlevar a = [1]; var b = a; a.length = 0; console.log(b)
打印出 Array [ ]
,所以在我看来它似乎并没有创建一个新的数组。 - John Montgomery对于while/pop和shift方法的性能问题,有很多混淆和错误的信息存在于答案和评论中。正如预期的那样,while/pop方案具有最差的性能。实际上发生的情况是,设置仅在运行循环中的代码段的每个样本时运行一次。例如:
var arr = [];
for (var i = 0; i < 100; i++) {
arr.push(Math.random());
}
for (var j = 0; j < 1000; j++) {
while (arr.length > 0) {
arr.pop(); // this executes 100 times, not 100000
}
}
我创建了一个新的测试,可以正确地工作:
http://jsperf.com/empty-javascript-array-redux
注意:即使在这个测试版本中,你实际上看不到真正的差异,因为克隆数组占据了大部分测试时间。它仍然显示出splice
是清空数组的最快方法(不考虑[]
,因为虽然它是最快的,但它实际上并没有清空现有的数组)。