Иногда необходимо объединить несколько массивов в один, содержащий элементы из исходных массивов. Для этого в 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