Как очистить массив в JavaScript?

2090

Есть ли способ очистить массив и, если возможно, с .remove()?

Например,

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

Как я могу удалить это?

  • 1
    вот эталон с разными возможностями: jsben.ch/#/7QyI1
Теги:
arrays

21 ответ

3687
Лучший ответ

Способы очистки существующего массива 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 (как предложил Мэтью Крамли)

A.length = 0

Это очистит существующий массив, установив его длину равным 0. Некоторые утверждают, что это может не работать во всех реализациях JavaScript, но оказывается, что это не так. Он также работает при использовании "строгого режима" в ECMAScript 5, потому что свойство length массива является свойством чтения/записи.

Метод 3 (как предложил Anthony)

A.splice(0,A.length)

Использование .splice() будет работать отлично, но поскольку функция .splice() вернет массив со всеми удаленными элементами, он фактически вернет копию исходного массива. Тесты показывают, что это не влияет на производительность вообще.

Метод 4 (как предложил tanguy_k)

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

Это решение не очень кратким, и оно также является самым медленным решением, в отличие от предыдущих эталонных тестов, упомянутых в исходном ответе.

Производительность

Из всех методов очистки существующего массива методы 2 и 3 очень похожи по производительности и намного быстрее, чем метод 4. См. этот тест.

Как указано Diadistis в их ответе ниже, исходные критерии, которые были использованы для определить эффективность четырех описанных выше методов были ошибочными. Исходный тест повторно использовал очищенный массив, поэтому вторая итерация очищала массив, который был уже пуст.

Следующий критерий устраняет этот недостаток: http://jsben.ch/#/hyj65. Он ясно показывает, что методы # 2 (свойство длины) и # 3 (сращивание) являются самыми быстрыми (не считая метод # 1, который не меняет исходный массив).


Это была горячая тема и причина многих споров. На самом деле есть много правильных ответов, и поскольку этот ответ был отмечен как принятый ответ в течение очень долгого времени, я буду включать все методы здесь. Если вы проголосуете за этот ответ, пожалуйста, подтвердите другие ответы, на которые я ссылался.

  • 157
    while (A.length) { A.pop(); } , нет необходимости для > 0
  • 279
    > 0 более читабельно ИМХО. И нет никакой разницы в производительности между ними.
Показать ещё 49 комментариев
2184

Если вам нужно сохранить исходный массив, потому что у вас есть другие ссылки на него, которые также должны быть обновлены, вы можете очистить его, не создавая новый массив, установив его длину в ноль:

A.length = 0;
  • 0
    Должно ли это работать со всеми браузерами?
  • 10
    @Acorn Да, это будет работать во всех браузерах.
Показать ещё 31 комментарий
278

Здесь самая быстрая рабочая реализация при сохранении одного и того же массива ("изменчивый"):

Array.prototype.clear = function() {
  while (this.length) {
    this.pop();
  }
};

Карта FYI определяет clear() поэтому было бы логично иметь clear() для массива.

Или как смесь Underscore.js:

_.mixin({
  clearArray: function(array) {
    while (array.length) {
      array.pop();
    }
  }
});

Или простая функция:

function clearArray(array) {
  while (array.length) {
    array.pop();
  }
}

Версия TypeScript:

function clearArray<T>(array: T[]) {
  while (array.length) {
    array.pop();
  }
}

FYI это не может быть упрощено while (array.pop()): тесты потерпят неудачу.

И тесты, которые идут с ним:

describe('Array', () => {
  it('should clear the array', () => {
    let array = [1, 2, 3, 4, 5];
    array.clear();
    expect(array.length).toEqual(0);
    expect(array[0]).toEqual(undefined);
    expect(array[4]).toEqual(undefined);

    // Even with undefined or null inside
    array = [1, undefined, 3, null, 5];
    array.clear();
    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

  • 5
    ТТ твой ответ - единственный, который правильный и быстрый (в то же время), но имеет гораздо меньше "голосов". Ну, похоже, что людям нравятся красивые решения, которые работают медленно: /
  • 0
    @naomik Но это одна из основных функций, которая должна была быть там по умолчанию.
Показать ещё 8 комментариев
180

Более дружественное к браузеру и более оптимальное решение будет заключаться в использовании метода splice для удаления содержимого массива A, как показано ниже:

A.splice(0, A.length);

  • 47
    Почему это более кросс-браузер дружественный? Какие браузеры имеют проблемы с A.length?
  • 0
    Как сказал @alex, splice возвращает новый массив. Не то, что вы хотели бы сделать в REPL . Вы всегда можете void выражение, но это не элегантное решение.
Показать ещё 8 комментариев
68

Ответы, которые имеют не менее 2739 upvotes, являются вводящими в заблуждение и неверными.

Возникает вопрос: "Как вы очищаете свой существующий массив?" Например. для A = [1,2,3,4].

  • Высказывание "A = [] является ответом" невежественно и абсолютно неверно. [] == [] false.

    Это связано с тем, что эти два массива представляют собой два отдельных отдельных объекта с их собственными двумя идентичностями, занимая свое собственное пространство в цифровом мире, каждый по отдельности.


Скажем, ваша мать просит вас очистить корзину.

  • Вы не вводите новый, как если бы вы сделали то, о чем вас просили.
  • Вместо этого вы очищаете корзину.
  • Вы не заменяете заполненную новую пустую банку, и вы не берете метку "A" из заполненной банки и не привязываете ее к новой, как в A = [1,2,3,4]; A = [];

Опорожнение объекта массива - это самая простая вещь:

A.length = 0;

Таким образом, банкнота под "А" не только пуста, но и чиста, как новая!


  1. Кроме того, вы не обязаны удалять мусор вручную, пока пустая пустая. Вас попросили полностью опорожнить существующий, за один ход, чтобы не забрать мусор, пока баннер не станет пустым, как в:

    while(A.length > 0) {
        A.pop();
    }
    
  2. Не оставляйте левую руку на дне корзины, удерживая ее справа вверху, чтобы вытащить ее содержимое, как в:

    A.splice(0, A.length);
    

Нет, вас попросили опорожнить его:

A.length = 0;

Это единственный код, который правильно опустошает содержимое данного массива JavaScript.

  • 8
    Единственная проблема с вашим предложенным решением состоит в том, что мусор все еще существует, просто вы изменили доску объявлений, говоря, что мусора нет. Ссылка на старый массив все еще должна существовать. Можете ли вы быть уверены, что сборщик мусора при установке .length = 0 также удалит все ссылки на массив и его свойства? Я думаю, что это так, но для меня это волшебство. Метод .clear () желательно избегать путаницы, если не сказать больше.
  • 0
    Нет солнца, это совсем не так. Возможно, вы захотите протестировать вещи и понять их достаточно глубоко, прежде чем пытаться возразить чему-то столь же безупречному, как эта базовая функциональность JavaScript. И это не «мое решение», это базовый синтаксис JS, который существует всегда. Сомнительно, как это может быть A.length = 0; это стандартный синтаксис для очистки вашего массива. Если вы хотите иметь такой метод, как A.clear , вы можете использовать этот стандартный синтаксис, чтобы легко добавить этот метод в ваши массивы: Array.prototype.clear = function(){this.length = 0} . Повеселись.
Показать ещё 7 комментариев
64

Тест производительности:

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
  • 9
    Добавление процентных изменений не очень полезно, не говоря уже о вашей платформе. На моей машине всплывающее окно в Chrome 34 работает очень быстро, но на самом деле медленнее, чем [] в последнем Firefox.
  • 2
    При тестировании в Firefox 39.0 32-битных в Windows NT 6.3 64-битных, a = [] является самым быстрым!
Показать ещё 6 комментариев
34

Вы можете добавить это в свой файл JavaScript, чтобы ваши "массивы" были очищены:

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);
    };
}

Многие думают, что вы не должны изменять собственные объекты (например, Array), и я склонен согласиться. Будьте осторожны при принятии решения о том, как с этим справиться.

  • 1
    @naomik Можете ли вы объяснить свои рассуждения о том, почему подобные вещи осуждаются?
  • 15
    Это "осуждается" для изменения примитивных функций javascript, таких как Array и String. Возможно, вы перегружаете уже существующую функцию и уничтожаете класс объекта. Там может быть неясный движок JavaScript, который уже имеет clear () и ожидает, что он будет вести себя по-другому. Поступайте осторожно, это все, что я говорю.
Показать ещё 2 комментария
16
Array.prototype.clear = function() {
    this.length = 0;
};

И назовите его: array.clear();

  • 74
    Пожалуйста, не поощряйте модификацию нативных объектов.
  • 18
    почему люди склонны брать принятый ответ и помещать его в функцию-прототип? Вы действительно делаете это в своих проектах? У вас есть огромная библиотека дополнений к прототипам, которые вы включаете в каждый проект?
Показать ещё 8 комментариев
15

Существует много путаницы и дезинформации относительно времени, поп/сдвиг, как в ответах, так и в комментариях. Решение 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 - это самый быстрый способ очистить массив (не учитывая [], потому что, хотя он самый быстрый, он фактически не очищает существующий массив).

  • 0
    Очень хороший момент! Я обновлю исходный ответ с правильными результатами теста.
  • 0
    Я не могу поверить, что никто не заметил эту ошибку. С более чем полумиллионом просмотров вы ожидаете, что кто-то заметит это. Отличная работа Диадистис
14

Если вы заинтересованы в распределении памяти, вы можете сравнить каждый подход, используя что-то вроде this jsfiddle в сочетании с вкладкой временной шкалы hrome dev tools. Вы захотите использовать значок корзины внизу, чтобы заставить сбор мусора после "очистки" массива. Это даст вам более конкретный ответ для браузера по вашему выбору. Многие ответы здесь старые, и я не буду опираться на них, а скорее проверю, как в ответе @tanguy_k выше.

(для входа в вышеупомянутую вкладку вы можете проверить здесь)

Stackoverflow заставляет меня скопировать jsfiddle, вот он:

<html>
<script>
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
}

</script>
<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 управляет строками иначе, чем другие примитивные типы, не говоря уже о массивах объектов. Тип может повлиять на то, что происходит.

11

Если вы используете

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, второй метод выполняется быстрее.

  • 9
    Помимо ошибки на a.length , я не вижу, что этот новый ответ добавляет в a.length ?
  • 0
    @ Берги Я просто хочу сосредоточиться на фактическом представлении памяти о массиве
Показать ещё 3 комментария
11

A.splice(0);

Я просто сделал это по некоторому коду, над которым я работаю. Он очистил массив.

  • 0
    Нет, вы просто поменяли именованный контейнер массива на вновь созданный анонимный. `var A = [1,2,3,4]; вар Б; B = A. splice (0); console.log (А); console.log (В); '
8

Вы можете легко создать функцию, которая сделает это для вас, изменить длину или даже добавить ее в собственный массив как функцию 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 элементов, он будет сращивать 5 элементов из 0, что означает, что в массиве ничего не останется.

Также другие способы, например, просто переназначить массив:

arr = []; //[]

Если вы посмотрите на функции массива, есть много других способов сделать это, но наиболее рекомендуемым может быть изменение длины.

Как я уже сказал, вы также можете прототипировать remove(), поскольку это ответ на ваш вопрос. вы можете просто выбрать один из вышеперечисленных методов и прототипировать его в объект Array в JavaScript, например:

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

и вы можете просто вызвать его так, чтобы очистить любой массив в вашем приложении javascript:

arr.remove(); //[]
8

Используйте измененную версию Jan первоначального предложения:

var originalLength = A.length;
for (var i = originalLength; i > 0; i--) {
     A.pop();
}
  • 12
    Почему вы хотите сделать такую вещь? Зачем добавлять еще две переменные и кучу кода, чтобы сделать то же самое?
6

Просто очистить массив

var  A = [1,2,3,4];   // array value 

A.length = 0 ;   // create empty array 

или

A = [];
5

Если вы используете константы, тогда у вас нет выбора:

const numbers = [1, 2, 3]

Вы не можете повторить:

numbers = []

Вы можете обрезать только:

numbers.length = 0
3

Я удивлен, что никто не предложил это еще:

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

Это дает массив в совершенно другом состоянии от других решений. В каком-то смысле массив был "опустошен":

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)

  • 5
    Это может быть хорошим ответом на другой вопрос: «Как преобразовать все элементы в массиве в неопределенные элементы».
3

Изображение 2054

Чтобы очистить текущую ячейку памяти массива, используйте: 'myArray.length = 0' или 'myArray.pop() UN-till its length is 0'

  • length: вы можете установить свойство length для усечения массива в любое время. Когда вы расширяете массив, изменяя его свойство length, число фактических элементов увеличивается.
  • pop(): метод pop удаляет элемент last из массива и возвращает, который возвращает удаленный значение.
  • shift(): метод shift удаляет элемент с нулевым индексом и сдвигает значения в последовательности индексы вниз, а затем возвращает удаленное значение.

Пример:

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 \n~ Current', mainArr, 'Refered', refArr);

mainArr.poptill_length(0);
console.log('Empty Array \n~ 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 constructor или array literal.

    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(): с помощью функции среза мы получаем мелкую копию элементов из исходного массива, с новым адресом памяти, Так что любая модификация на cloneArr не повлияет на фактический исходный массив.

    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);
    
  • 0
    msgstr "длина: появляется до длины массива указанного размера." Кто сказал тебе эту глупость?
  • 0
    @BekimBacaj По сути, это делает тот же эффект. Вероятно, следовало сказать, length = ? вместо просто length .
Показать ещё 1 комментарий
2
var arr = [1,2,3,5];

Вы можете использовать:

1. arr.length = 0;
2. arr.splice(0);
3. arr = arr.constructor();
4. arr = [];
0

Сравнение поведения между циклами arr = [] vs a arr.pop():

var arr = [1,2,3];
var arrCopy = arr;
arr = [];
console.log(arrCopy.length); /* Outputs 3: arr points to a NEW array (which is empty), and arrCopy still points to [1,2,3]. */

var brr = [4,5,6,7];
var brrCopy = brr;
while (brr.length) {
    brr.pop();
}
console.log(brrCopy.length); /* Outputs 0: brr and brrCopy points to the same array, whose elements are removed in the loop. */
-4

Используйте ниже, если вам нужно удалить Angular 2+ FormArray.

public emptyFormArray(formArray:FormArray) {
    for (let i = formArray.controls.length - 1; i >= 0; i--) {
        formArray.removeAt(i);
    }
}
  • 7
    Это не имеет значения и даже не JavaScript.
  • 0
    почему этот парень существует ??

Ещё вопросы

Сообщество Overcoder
Наверх
Меню