Pull to refresh

Почему не надо удалять все элементы массива, переназначая его на [ ]?

Reading time 3 min
Views 8.5K
Original author: Yogesh Chavan

Очень часто бывают моменты, когда мы хотим удалить все элементы массива, как вариант, у нас есть список задач, и мы хотим удалить все задачи одновременно.


Рассмотрим такой список элементов:


let items = ["tea", "coffee", "milk"];

Чтобы удалить все элементы из массива, мы устанавливаем его значение в пустой массив


items = [];

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



Посмотрим на следующий код:


let items = ["tea", "coffee", "milk"];
let copy = items;

Здесь мы создаем переменную copy и присваиваем ей ссылку на массив элементов, так что copy фактически указывает на массив items.


Убедимся в этом проверив их индивидуальные значения


console.log(items); // ["tea", "coffee", "milk"]
console.log(copy); // ["tea", "coffee", "milk"]

Всё как и ожидалось.


Теперь, если мы изменим какой-либо из элементов, он изменит сам исходный массив, так как это просто ссылка, а не точная копия.


copy[2] = "oranges";
console.log(items); // ["tea", "coffee", "oranges"]
console.log(copy); // ["tea", "coffee", "oranges"]

Но если мы хотим удалить все элементы массива items, мы, обычно, делаем так:


items = [];

Теперь, если мы проверим значения items и copy снова


console.log(items); // []
console.log(copy); // ["tea", "coffee", "oranges"]

Как вы можете видеть, массив items пуст, но вот переменная copy все еще содержит исходный массив и не очистилась.


Это произошло потому, что когда мы написали items = [], переменная фактически создала новый пустой массив и присвоила его элементам, чтобы не изменять переменную copy.


Для не примитивных типов данных, таких как массив(array), или объект(object), когда мы присваиваем какое-либо значение, оно устанавливает не фактическое значение, а только ссылку на выделенный адрес памяти, где хранится эта переменная.


Поэтому, когда мы говорим, array = [], [] — это краткий способ выделения некоторого пространства в памяти без данных, поэтому массив будет содержать только ссылку на выделенное пространство памяти.


То же самое относится и к объектам. Когда мы говорим obj = {name: 'David'}, переменная obj содержит не сам объект, а просто ссылку на выделенное пространство памяти, и в этом пространстве памяти сохраняется фактический объект.


let obj = { name: 'David' };
let newObj = obj;
console.log(obj); // { name: 'David' }
console.log(newObj); // { name: 'David' }
obj = null;
console.log(obj); // null
console.log(newObj); // { name: 'David' }

Чтоб исправить это неподобство есть два способа:


  1. Установите длину массива в 0:
    let items = ["tea", "coffee", "milk"];
    let copy = items;
    console.log(items); // ["tea", "coffee", "milk"]
    console.log(copy); // ["tea", "coffee", "milk"]
    items.length = 0;
    console.log(items); // []
    console.log(copy); // []
  2. Используйте метод splice массива:
    let items = ["tea", "coffee", "milk"];
    let copy = items;
    console.log(items); // ["tea", "coffee", "milk"]
    console.log(copy); // ["tea", "coffee", "milk"]
    // удаляем элементы массива, начиная с позиции 0 до последнего элемента длины массива
    items.splice(0, items.length);
    console.log(items); // []
    console.log(copy); // []

Этот способ решает нашу задачу, потому что они фактически изменяют исходный массив, а не просто изменяют ссылку на элементы, как в случае с items = [];


Заключение:


Мы не должны создавать дополнительные ссылки для массива или объекта, так как это может привести к нежелательному результату в будущем. Если вы уверены, что нет никаких ссылок(*и не появится) на исходный массив, который нам нужно очистить, то вы можете использовать array = [], чтобы очистить его, иначе используйте любой из двух вышеперечисленных способов, чтобы очистить массив.


Сделаем web лучше.
Tags:
Hubs:
-44
Comments 51
Comments Comments 51

Articles