Blog. Just Blog

Как скопировать массив на JavaScript

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
При программировании на JavaScript иногда требуется создать копию массива. Но особенность заключается в том, что в JavaScript массив является объектом, поэтому при использовании оператора присваивания, новой копии создаваться не будет, а просто будет создана ссылка на существующий массив. Если после этого попробовать внести какие-нибудь изменения в любой из этих массивов, то изменения будут внесены сразу в оба. Так получается, потому что фактически это один и тот же объект. Например:
  1. // Как хочется сделать, но не получится
  2. var old_array = ['one''two''three'];
  3. var new_array old_array;
  4.  
  5. // Добавляем по одному элементу в исходный и "новый" массив
  6. old_array.push('banana');
  7. new_array.push('lemon');
  8.  
  9. // Получается вот что
  10. // old_array = ['one', 'two', 'three', 'banana', 'lemon'];
  11. // new_array = ['one', 'two', 'three', 'banana', 'lemon'];
Как видите, несмотря на то, что мы пытались добавить элементы в разные массивы (как нам казалось), они добавились в оба. Чтобы создавать не ссылку, а копию, можно воспользоваться хитрым трюком с методом slice. В этом случае будет создана именно копия массива.
  1. // Корректный вариант решения
  2. var old_array = ['one''two''three'];
  3. var new_array old_array.slice(0);
  4.  
  5. // Добавляем по одному элементу в исходный и новый массив
  6. old_array.push('banana');
  7. new_array.push('lemon');
  8.  
  9. // Теперь все правильно
  10. // old_array = ['one', 'two', 'three', 'banana'];
  11. // new_array = ['one', 'two', 'three', 'lemon'];
Надеюсь, что этот совет вам где-нибудь пригодится и поможет избежать хитрых ошибок, которые достаточно сложно отловить.

Поделиться ссылкой ВКонтакте
Просмотров: 4740 | Комментариев: 6

Метки: JavaScript
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
artem (15.08.2016 в 15:33):
На больший массивах будут лютые тормоза!
superpuper (26.05.2014 в 23:49):
Даже по указанной в статье ссылке написано, что первый аргумент — required, т.е. необходим. Так что .slice(0), иначе ошибка. В FF так точно.
ManHunter (30.05.2013 в 21:10):
Век живи - век учись :)
unreal666 (30.05.2013 в 12:07):
точнее, в прототипах хранить только неизменяемые методы/свойства, к которым могут относиться, к примеру, и константы.
superpuper (30.05.2013 в 00:33):
Отсюда мораль : методы — в прототипах, свойства(т.е. данные) — в экземплярах. И никак иначе.
Infocatcher (29.05.2013 в 12:30):
Хитрые ошибки будут вот тут:
function Collector() {
}
Collector.prototype = {
    data: [],
    add: function(v) {
        this.data.push(v);
    }
};
var collector1 = new Collector();
collector1.add(1);
var collector2 = new Collector();
collector2.add(2);
alert(collector1.data); // [1, 2]

Правильно при этом вот так:
function Collector() {
    this.data = [];
}
Collector.prototype = {
    add: function(v) {
        this.data.push(v);
    }
};
То есть чтобы у каждого экземпляра был свой массив.

Тут, правда, не так чтобы особенно хитро – все логично, но попасться можно.
Особенно с учетом вот такого:
function Counter() {
}
Counter.prototype = {
    index: 0,
    inc: function() {
        ++this.index;
    }
};
var counter1 = new Counter();
counter1.inc();
var counter2 = new Counter();
counter2.inc();
alert(counter1.index + "\n" + counter2.index);

Фокус, соответственно, в том, что ++ делает this.index = this.index + 1, то есть переопределяет свойство, а this уже указывает на экземпляр. И получается примерно такое:
function Counter() {
    this.index = 1;
}
Counter.prototype = {
    index: 0
};
var counter = new Counter();
alert(Counter.prototype.index + "\n" + counter.index);


(Я правильно понимаю, что в коменнтариях блоки с кодом не поддерживаются?)

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0044 сек.) / Память: 4.5 Mb
Наверх