Как очистить массив в JavaScript?
Есть ли способ очистить массив и, если возможно, с .remove()
?
Например,
A = [1,2,3,4];
Как я могу очистить это?
18 ответов
Способы очистки существующего массива 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
Это очистит существующий массив, установив его длину равным 0. Некоторые утверждают, что это может работать не во всех реализациях JavaScript, но оказывается, что это не так. Это также работает при использовании "строгого режима" в ECMAScript 5, потому что свойство длины массива является свойством чтения / записи.
Метод 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/. Это ясно показывает, что методы #2 (свойство length) и #3 (соединение) являются самыми быстрыми (не считая метода #1, который не изменяет исходный массив).
Это была горячая тема и причина многих противоречий. На самом деле есть много правильных ответов, и поскольку этот ответ был помечен как принятый ответ в течение очень долгого времени, я включу все методы здесь. Если вы проголосуете за этот ответ, пожалуйста, проголосуйте за другие ответы, на которые я также ссылался.
Если вам нужно сохранить исходный массив, потому что у вас есть другие ссылки на него, которые также должны быть обновлены, вы можете очистить его, не создавая новый массив, установив его длину в ноль:
A.length = 0;
Здесь самая быстрая рабочая реализация, сохраняя тот же массив ("изменяемый"):
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();
}
}
К вашему сведению это не может быть упрощено до 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
Более кросс-браузерным и более оптимальным решением будет использование splice
метод для очистки содержимого массива A, как показано ниже:
A.splice(0, A.length);
Ответы, которые к настоящему времени имеют не менее 2739 голосов, вводят в заблуждение и неверны.
Вопрос в следующем: "Как очистить существующий массив?" Например, для A = [1,2,3,4]
,
Сказать "
A = []
это ответ "невежественен и абсолютно неверен.[] == []
ложноЭто потому, что эти два массива являются двумя отдельными, индивидуальными объектами, со своими собственными двумя идентичностями, занимающими свое собственное пространство в цифровом мире, каждый сам по себе.
Допустим, твоя мать просит тебя очистить мусорное ведро.
- Вы не вводите новый, как будто вы сделали то, о чем вас просили.
- Вместо этого вы опустошаете мусорное ведро.
- Вы не заменяете заполненную банку новой пустой банкой, и вы не берете этикетку "А" из наполненной банки и прикрепляете ее к новой, как в
A = [1,2,3,4]; A = [];
Очистка объекта массива - самая простая вещь:
A.length = 0;
Таким образом, банка под "А" не только пуста, но и чиста, как новая!
Кроме того, вы не обязаны убирать мусор вручную, пока банка не опустеет! Вас попросили полностью опустошить существующую за один ход, чтобы не собирать мусор до тех пор, пока банка не опустеет, как в:
while(A.length > 0) { A.pop(); }
Кроме того, чтобы положить левую руку в нижнюю часть корзины, удерживая ее правой стороной вверху, чтобы можно было извлечь ее содержимое, как показано ниже:
A.splice(0, A.length);
Нет, вас попросили очистить его:
A.length = 0;
Это единственный код, который корректно очищает содержимое данного массива JavaScript.
Тест производительности:
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
Вы можете добавить это в свой файл 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), и я склонен согласиться. Пожалуйста, будьте осторожны при решении, как справиться с этим.
Вы можете легко создать функцию, которая сделает это за вас, изменить длину или даже добавить ее в собственный массив как 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 = []; //[]
Если вы посмотрите на функции Array, есть много других способов сделать это, но наиболее рекомендуемым может быть изменение длины.
Как я уже сказал, вы также можете создать прототип remove(), так как это ответ на ваш вопрос. Вы можете просто выбрать один из методов выше и создать его прототип для объекта Array в JavaScript, например:
Array.prototype.remove = Array.prototype.remove || function() {
this.splice(0, this.length);
};
и вы можете просто вызвать его так, чтобы очистить любой массив в вашем приложении javascript:
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, второй метод быстрее.
Существует много путаницы и дезинформации в отношении времени, популярности / смены как в ответах, так и в комментариях. Решение 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
это самый быстрый способ очистить массив (не принимая []
во внимание, потому что, хотя он самый быстрый, он на самом деле не очищает существующий массив).
Array.prototype.clear = function() {
this.length = 0;
};
И назовите это: array.clear();
Если вас интересует распределение памяти, вы можете сравнить каждый подход, используя что-то вроде этого jsfiddle в сочетании с вкладкой временной шкалы инструментов Chrome Dev. Вы захотите использовать значок мусорной корзины внизу, чтобы принудительно запустить сборку мусора после "очистки" массива. Это должно дать вам более определенный ответ для браузера по вашему выбору. Многие ответы здесь старые, и я бы не стал на них полагаться, а скорее протестировал, как в ответе @tanguy_k выше.
(для ознакомления с вышеупомянутой вкладкой вы можете проверить здесь)
Stackru заставляет меня скопировать 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 управляет строками иначе, чем другие примитивные типы, не говоря уже о массивах объектов. Тип может влиять на то, что происходит.
Используйте измененную версию первоначального предложения Jan:
var originalLength = A.length;
for (var i = originalLength; i > 0; i--) {
A.pop();
}
A.splice(0);
Я только что сделал это с кодом, над которым я работаю. Это очистило массив.
Если вы используете константы, то у вас нет выбора:
const numbers = [1, 2, 3]
Вы не можете переназначить:
numbers = []
Вы можете только усечь:
numbers.length = 0
Чтобы очистить текущую ячейку памяти массива, используйте: 'myArray.length = 0'
или же 'myArray.pop() UN-till its length is 0'
length
: Вы можете установить свойство length для усечения массива в любое время. Когда вы расширяете массив, изменяя его свойство length, количество реальных элементов увеличивается.pop()
: Метод pop удаляет последний элемент из массива и возвращает возвращаемое удаленное значение.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);
Я удивлен, что никто еще не предложил это:
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)
Используйте ниже, если вам нужно очистить Angular 2+ FormArray.
public emptyFormArray(formArray:FormArray) {
for (let i = formArray.controls.length - 1; i >= 0; i--) {
formArray.removeAt(i);
}
}