Объединение, деление и клонирование массивов


Объединение массивов Иногда необходимо объединить несколько массивов в один, содержащий элементы из исходных массивов. Для этого в JavaScript есть метод concat. Он создаёт копию исходного массива, добавляя к нему переданные аргументы, подобно методу push. Однако, в отличие от push, если методу concat передан другой массив, то будут добавлены элементы этого массива, а не сам массив единственным элементом. Array.prototype.toString = function() { return '[' + this.join(', ') + ']'; }; var a = [1, 2, 3]; alert(a.concat(4, 5, 6)); // [1, 2, 3, 4, 5, 6] alert(a.concat([4, 5], [6])); // [1, 2, 3, 4, 5, 6] Однако дальше одного уровня concat аргументы-массивы не разворачивает. Array.prototype.toString = function() { return '[' + this.join(', ') + ']'; }; var a = [1, 2, 3]; alert(a.concat([4, [5], 6])); // [1, 2, 3, 4, [5], 6] С разреженными массивами ситуация обстоит ожидаемая: пропуски как из исходного массива, так и из массивов-аргументов, сохраняются. Array.prototype.toString = function() { return '[' + this.join(', ') + ']'; }; var a = [1, , 3]; alert(a.concat([4, , 6])); // [1, , 3, 4, , 6] Деление массива Метод slice имеет сигнатуру slice(begin[, end]) и возвращает подмассив исходного массива, начиная с индекса begin и заканчивая индексом end - 1. Чтобы легче запомнить такую странную нумерацию, лучше считать, что передаются индексы не элементов, а "межэлементного пространства". Индексы элементов: 0 1 2 3 4 5 6 7 8 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | Индексы для slice: 0 1 2 3 4 5 6 7 8 9 Тогда становится понятно, что ar.slice(0, 1) вернёт только нулевой элемент, а slice(5, 9) — с пятого по восьмой элементы. var a = [0, 1, 2, 3, 4, 5]; alert(a.slice(0, 2)); // 0,1 alert(a.slice(4, 5)); // 4 Если второй аргумент является отрицательным числом, то отсчёт второго индекса идёт с конца массива. var a = [0, 1, 2, 3, 4, 5]; alert(a.slice(0, -2)); // 0,1,2,3 Если же второй аргумент не передан вообще, то возвращается копия массива от begin до конца. var a = [0, 1, 2, 3, 4, 5]; alert(a.slice(3)); // 3,4,5 Клонирование массива В JavaScript нет нативного метода для клонирования массивов, однако его легко сэмулировать, помня, что concat и slice не меняют исходный массив. Достаточно вызвать метод concat без аргументов или метод slice с единственным аргументом равным 0. var a = [1, 2, 3]; var b = a.concat(); var c = a.slice(0); alert(a + ' ; ' + b + ' ; ' + c); // 1,2,3 ; 1,2,3 ; 1,2,3 alert([a == b, a == c, b == c]); // false,false,false Обратите внимание, если в массиве лежат ссылки на объекты, в том числе ссылки на другие массивы, то в новосозданном массиве будут лежать ссылки на те же самые объекты. Поэтому если вы хотите клонировать многомерный массив, то придётся вручную создавать новый массив, после чего перебрать подмассивы исходного массива и клонировать их в новый. // Клонируется только массив верхнего уровня var a = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; var b = a.concat(); alert(a[0][1]); // 2 alert(b[0][1]); // 2 b[0][1] = 15; alert(a[0][1]); // 15 // Клонируем вложенные массивы var a = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; var b = []; a.forEach(function(subArray) { b.push(subArray.concat()); }); alert(a[0][1]); // 2 alert(b[0][1]); // 2 b[0][1] = 15; alert(a[0][1]); // 2