如何清空javascript中的数组?

How do I empty an array in JavaScript?

有没有一种方法可以清空一个数组,如果可能的话,还可以使用.remove()

例如,

1
A = [1,2,3,4];

我该怎么倒?


清除现有数组A的方法:

方法1

(这是我对这个问题的原始答案)

1
A = [];

此代码将把变量A设置为新的空数组。如果您没有在任何其他地方引用原始数组A,这是完美的,因为这实际上创建了一个全新的(空)数组。您应该小心使用此方法,因为如果您从另一个变量或属性引用了此数组,原始数组将保持不变。仅当您仅通过数组的原始变量A引用数组时才使用此选项。

这也是最快的解决方案。

此代码示例显示使用此方法时可能遇到的问题:

1
2
3
4
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建议)

1
A.length = 0

这将通过将现有数组的长度设置为0来清除该数组。一些人认为这可能不适用于所有的JavaScript实现,但事实证明并非如此。它在ECMAScript 5中使用"严格模式"时也可以工作,因为数组的长度属性是读/写属性。

方法3(安东尼建议)

1
A.splice(0,A.length)

使用.splice()将很好地工作,但是由于.splice()函数将返回一个包含所有已删除项的数组,因此它实际上将返回原始数组的副本。基准测试表明,这对业绩没有任何影响。

方法4(根据Tanguy_k的建议)

1
2
3
while(A.length > 0) {
    A.pop();
}

这个解决方案不是很简洁,也是最慢的解决方案,与最初答案中引用的早期基准相反。

性能

在清除现有数组的所有方法中,方法2和3的性能非常相似,并且比方法4快得多。看看这个基准。

正如Diadistis在下面的答案中指出的,用于确定上述四种方法性能的原始基准存在缺陷。原始基准重新使用已清除的数组,因此第二次迭代正在清除已为空的数组。

以下基准修复了此缺陷:http://jsben.ch//hyj65。它清楚地表明,方法2(长度属性)和3(拼接)是最快的(而不是不改变原始数组的计数方法1)。


这一直是一个热门话题,引起了很多争议。实际上有很多正确的答案,因为这个答案已经被标记为公认的答案很长一段时间了,我将在这里包括所有的方法。如果你对这个答案投赞成票,请把我提到的其他答案也投反对票。


如果需要保留原始数组,因为对它的其他引用也应更新,则可以通过将其长度设置为零来清除它,而不创建新数组:

1
A.length = 0;


这里是最快的工作实现while keeping the same array("mutable"):

1
2
3
4
5
function clearArray(array) {
  while (array.length) {
    array.pop();
  }
}

仅供参考,它不能简化为while (array.pop()):测试将失败。

fyi map和set define clear(),将clear()用于数组似乎也是合乎逻辑的。

类型脚本版本:

1
2
3
4
5
function clearArray<T>(array: T[]) {
  while (array.length) {
    array.pop();
  }
}

相应的测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
  });
});

这里更新的jspef:http://jspef.com/array destroy/32http://jspef.com/array-destroy/152


一个更为跨浏览器友好和最佳的解决方案是使用splice方法清空数组A的内容,如下所示:

A.splice(0, A.length);


到目前为止,获得不少于2739张赞成票的答案是误导性的和不正确的。

问题是:"如何清空现有数组?"例如,对于A = [1,2,3,4]

  • 说"江户一〔5〕是答案"是无知和绝对错误的。[] == []是假的。

    这是因为这两个阵列是两个独立的独立对象,具有各自的两个身份,在数字世界中占据各自的空间,各自独立。

  • 比如说,你妈妈让你把垃圾桶倒空。

    • 你不会像按要求做的那样带来新的。
    • 相反,你倒空垃圾桶。
    • 你不能用一个新的空罐替换装满的罐,也不能从装满的罐上取下标签"A"并把它贴在新的罐上,如A = [1,2,3,4]; A = [];所示。

    清空数组对象是最简单的事情:

    1
    a.length = 0;

    这样一来,"A"下的罐子不仅是空的,而且像新的一样干净!

  • 此外,在垃圾桶清空之前,您不需要手动清除垃圾!你被要求一次性清空现有的垃圾桶,直到垃圾桶清空,如:

    1
    2
    3
    while(a.length > 0) {
        a.pop();
    }
  • 也不要把你的左手放在垃圾桶的底部,右手放在垃圾桶的顶部,这样你就可以把垃圾桶里的东西拿出来,就像:

    1
    A.splice(0, A.length);
  • 不,你被要求清空它:

    1
    a.length = 0;

    这是唯一正确清空给定javascript数组内容的代码。


    性能测试:

    http://jspef.com/array-clear-methods/3

    1
    2
    3
    4
    5
    6
    a = []; // 37% slower
    a.length = 0; // 89% slower
    a.splice(0, a.length)  // 97% slower
    while (a.length > 0) {
        a.pop();
    } // Fastest


    您可以将此添加到您的javascript文件中,以允许"清除"您的数组:

    1
    2
    3
    Array.prototype.clear = function() {
        this.splice(0, this.length);
    };

    然后你可以这样使用它:

    1
    2
    var list = [1, 2, 3];
    list.clear();

    或者,如果你想确定你没有销毁什么东西:

    1
    2
    3
    4
    5
    if (!Array.prototype.clear) {
        Array.prototype.clear = function() {
           this.splice(0, this.length);
        };
    }

    很多人认为你不应该修改本地对象(比如数组),我倾向于同意。请谨慎决定如何处理。


    在回答和评论中有很多关于while;pop/shift性能的混淆和错误信息。while/pop解决方案(如预期)的性能最差。实际上,对于在循环中运行代码段的每个示例,安装程序只运行一次。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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://jspef.com/empty-javascript-array-redux

    警告:即使在这个版本的测试中,您也看不到真正的区别,因为克隆数组会占用大部分测试时间。它仍然表明,splice是清除阵列的最快方法(不考虑[],因为虽然它是最快的,但实际上并没有清除现有阵列)。


    1
    2
    3
    Array.prototype.clear = function() {
        this.length = 0;
    };

    叫它:array.clear();


    如果您对内存分配感兴趣,可以将每个方法与chrome dev工具的时间线选项卡结合使用类似于此jfiddle的工具进行比较。您将希望在"清除"数组后使用底部的垃圾箱图标强制垃圾收集。这将为您选择的浏览器提供更明确的答案。这里的很多答案都是老生常谈的,我不会依赖它们,而是像上面的@tanguy_k's answer中的测试。

    (有关上述选项卡的介绍,您可以在此处查看)

    StackOverflow强制我复制jsFiddle,所以这里是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <html>

    var size = 1000*100
    window.onload = function() {
      document.getElementById("quantifier").value = size
    }

    function scaffold()
    {
      console.log("processing Scaffold...");
      a = new Array
    }
    function start()
    {
      size = document.getElementById("quantifier").value
      console.log("Starting... quantifier is" + size);
      console.log("starting test")
      for (i=0; i<size; i++){
        a[i]="something"
      }
      console.log("done...")
    }

    function tearDown()
    {
      console.log("processing teardown");
      a.length=0
    }


    <body>
        <span style="color:green;">Quantifier:</span>
        <input id="quantifier" style="color:green;" type="text"></input>
        <button onclick="scaffold()">Scaffold</button>
        <button onclick="start()">Start</button>
        <button onclick="tearDown()">Clean</button>
        <br/>
    </body>
    </html>

    您应该注意,它可能取决于数组元素的类型,因为JavaScript管理字符串的方式与其他基元类型不同,更不用说对象数组。类型可能会影响发生的情况。


    A.splice(0);

    我只是在我正在处理的代码上做了这个。它清除了阵列。


    如果您正在使用

    1
    a = [];

    然后将新的数组引用分配给,如果在中的引用已经分配给任何其他变量,则它也不会清空该数组,因此垃圾收集器不会收集该内存。

    为Ex.

    1
    2
    3
    4
    var a=[1,2,3];
    var b=a;
    a=[];
    console.log(b);// It will print [1,2,3];

    1
    a.length = 0;

    当我们指定a.length时,我们只是重置数组的边界,其余数组元素的内存将由垃圾收集器连接。

    而不是这两个解决方案更好。

    1
    a.splice(0,a.length)

    1
    2
    3
    while(a.length > 0) {
        a.pop();
    }

    根据kenshou.html之前的答案,第二种方法更快。


    您可以很容易地创建一个函数来实现这一点,更改长度,甚至将其作为remove()函数添加到本机数组中以供重用。

    假设您有这个数组:

    1
    var arr = [1, 2, 3, 4, 5]; //the array

    好的,只需运行以下命令:

    1
    arr.length = 0; //change the length

    结果是:

    1
    [] //result

    清空数组的简单方法…

    也可以使用循环,这不是必需的,但只是另一种方法:

    1
    2
    3
    4
    5
    6
    7
    8
    /* 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();
      }
    }

    还有一些棘手的方法可以考虑,例如:

    1
    arr.splice(0, arr.length); //[]

    因此,如果arr有5个项目,它将从0中拼接5个项目,这意味着数组中不会保留任何内容。

    其他方法,例如简单地重新分配数组:

    1
    arr = []; //[]

    如果您查看数组函数,有许多其他方法可以做到这一点,但最推荐的方法是更改长度。

    正如我在第一个地方所说,您还可以原型remove(),因为它是您问题的答案。您可以简单地选择上面的方法之一,并将其原型化为JavaScript中的数组对象,如下所示:

    1
    2
    3
    Array.prototype.remove = Array.prototype.remove || function() {
      this.splice(0, this.length);
    };

    您可以这样简单地调用它来清空JavaScript应用程序中的任何数组:

    1
    arr.remove(); //[]

    使用简的初始建议的修改版本:

    1
    2
    3
    4
    var originalLength = A.length;
    for (var i = originalLength; i > 0; i--) {
         A.pop();
    }


    如果使用常量,则没有选择:

    1
    const numbers = [1, 2, 3]

    您不能重新签名:

    1
    numbers = []

    只能截断:

    1
    numbers.length = 0

    enter image description here

    清空阵列的当前内存位置:'myArray.length = 0''myArray.pop() UN-till its length is 0'

    • length:可以随时设置长度属性来截断数组。通过更改数组的长度属性来扩展数组时,实际元素的数量会增加。
    • pop():pop方法从数组中删除最后一个元素,并返回已删除的值。
    • shift():shift方法删除零索引处的元素,并向下移动连续索引处的值,然后返回删除的值。

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    var arr = ['77'];
    arr.length = 20;
    console.log("Increasing :", arr); // (20) ["77", empty × 19]
    arr.length = 12;
    console.log("Truncating :", arr); // (12) ["77", empty × 11]

    var mainArr = new Array();
    mainArr = ['1', '2', '3', '4'];

    var refArr = mainArr;
    console.log('Current', mainArr, 'Refered', refArr);

    refArr.length = 3;
    console.log('Length: ~ Current', mainArr, 'Refered', refArr);

    mainArr.push('0');
    console.log('Push to the End of Current Array Memory Location
    ~ Current'
    , mainArr, 'Refered', refArr);

    mainArr.poptill_length(0);
    console.log('Empty Array
    ~ Current'
    , mainArr, 'Refered', refArr);

    Array.prototype.poptill_length = function (e) {
      while (this.length) {
        if( this.length == e ) break;

        console.log('removed last element:', this.pop());
      }
    };
    • new Array() | []通过使用Array constructorarray literal创建具有新内存位置的数组。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      mainArr = []; // a new empty array is addressed to mainArr.

      var arr = new Array('10'); // Array constructor
      arr.unshift('1'); // add to the front
      arr.push('15'); // add to the end
      console.log("After Adding :", arr); // ["1","10","15"]

      arr.pop(); // remove from the end
      arr.shift(); // remove from the front
      console.log("After Removing :", arr); // ["10"]

      var arrLit = ['14', '17'];
      console.log("array literal ?", indexedItem( arrLit ) ); // {0,14}{1,17}

      function indexedItem( arr ) {
          var indexedStr ="";
          arr.forEach(function(item, index, array) {
              indexedStr +="{"+index+","+item+"}";
              console.log(item, index);
          });
          return indexedStr;
      }
    • slice():通过使用slice函数,我们从原始数组中得到一个具有新内存地址的元素的浅拷贝,这样对clonear的任何修改都不会影响到实际的原始数组。

      1
      2
      3
      4
      5
      6
      7
      var shallowCopy = mainArr.slice(); // this is how to make a copy

      var cloneArr = mainArr.slice(0, 3);
      console.log('Main', mainArr, '\tCloned', cloneArr);

      cloneArr.length = 0; // Clears current memory location of an array.
      console.log('Main', mainArr, '\tCloned', cloneArr);


    我很惊讶还没有人提出这样的建议:

    1
    2
    3
    let xs = [1,2,3,4];
    for (let i in xs)
        delete xs[i];

    这将生成一个与其他解决方案处于完全不同状态的数组。在某种意义上,数组已"清空":

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    xs
    => Array [ <4 empty slots> ]

    [...xs]
    => Array [ undefined, undefined, undefined, undefined ]

    xs.length
    => 4

    xs[0]
    => ReferenceError: reference to undefined property xs[0]

    您可以使用[,,,,]Array(4)生成等效数组。


    如果需要清空Angular 2+Formarray,请在下面使用。

    1
    2
    3
    4
    5
    public emptyFormArray(formArray:FormArray) {
        for (let i = formArray.controls.length - 1; i >= 0; i--) {
            formArray.removeAt(i);
        }
    }