Все о массивах в JavaScript в 1 статье

Все о массивах в JavaScript в 1 статье

От автора: все, что нужно знать о том, как работают в JavaScript массивы и мой любимый метод reduce(). Массивы – это аккуратный способ хранения непрерывных элементов в памяти в виде одной переменной. Элементы в массиве доступны по индексам. Индексы массива начинаются с 0.

Давайте создадим пустой массив разными способами.

let tasks = [];
let projects = new Array();

Массивы в JS обозначаются квадратными скобками []. Взять длину массива или количество элементов в нем можно с помощью свойства length.

tasks.length; // returns 0;
projects.length; // return 0;

В конструкторе Array можно задать начальную длину массива, чего нельзя сделать с массивом, созданным с помощью квадратных скобок.

Например:

let projects = new Array(10);
console.log(projects.length); // Outputs 10

Рекомендуемый способ использования [] для создания массивов

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

Все примеры далее будут использовать [].

Давайте сохраним пару значений в массив и обратимся к ним по индексу

Заметка: в массиве можно хранить что угодно, но для лучшей производительности храните данные только одного типа в одном массиве. Например, массив текста, чисел, объектов и т.д. Не смешивайте типы (по крайней мере, старайтесь избегать этого).

let projects = ['Learn Spanish', 'Learn Go', 'Learn Erlang'];

Обратиться к элементам массива можно по индексу следующим образом.

console.log(projects[0]); // Outputs 'Learn Spanish'
console.log(projects[2]); // Outputs 'Learn Erlang';
console.log(projects[3]); // Outputs 'undefined' 

Добавление элементов в массив

Добавление элементов в конец массива (метод push)

Добавим пару элементов в конец массива. Для этого используем метод push().

projects.push("Learn Malayalam");
console.log(projects); // ["Learn Spanish", "Learn Go", "Learn Erlang", "Learn Malayalam"] 

Заметка: метод push() мутирует массив. Для удаления элементов из массива используйте метод pop().

Добавление элементов в начало массива (unshift)

Добавим пару элементов в начало массива. Для этого используем метод unshift().

projects.unshift("Learn Tamil");
console.log(projects);
// ["Learn Tamil", "Learn Spanish", "Learn Go", "Learn Erlang", "Learn Malayalam"] 

Заметка: unshift() мутирует массив.

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

projects.unshift("Learn French", "Learn Marathi");
console.log (projects);
// ["Learn French", "Learn Marathi", "Learn Tamil", "Learn Spanish", "Learn Go", "Learn Erlang", "Learn Malayalam"] 

Добавление элементов в начало массива ES6 (оператор расширения)

let projects = ['Learn Spanish', 'Learn Go', 'Learn Erlang'];
projects = ['Learn Malayalam', ...projects];
console.log(projects);
//Outputs-> ['Learn Malayalam', 'Learn Spanish', 'Learn Go', 'Learn Erlang'] 

Добавление элементов в конец массива ES6 (оператор расширения)

let projects = ['Learn Spanish', 'Learn Go', 'Learn Erlang'];
projects = [...projects,'Learn Malayalam'];
console.log(projects);
//Outputs-> ['Learn Spanish', 'Learn Go', 'Learn Erlang','Learn Malayalam'] 

Заметка: способ с ES6 не мутирует массив и возвращает новый обновленный массив.

Удаление первого элементов из массива -> метод shift()

Метод shift() удаляет первый элемент из массива и возвращает его. Этот метод меняет длину массива. Если массив пуст, возвращается undefined.

let numbers = [1,2,3,4];
let firstNo = numbers.shift();
console.log(numbers); // [2,3,4];
console.log(firstNo); // 1 

Удаление части массива, разрезание -> метод slice()

Slice method MDN Reference – довольно полезный метод, позволяющий отрезать массив с любой точки.

Метод slice() возвращает копию части массива в виде нового объекта массива с выбранными begin и end (end не включительно). Исходный массив не меняется.

arr.slice([begin[, end]]) 

Разберем несколько примеров.

var elements = ['Task 1', 'Task 2', 'Task 3', 'Task 4', 'Task 5']; elements.slice(2) //["Task 3", "Task 4", "Task 5"]
elements.slice(2,4) // ["Task 3", "Task 4"]
elements.slice(1,5) // ["Task 2", "Task 3", "Task 4", "Task 5"]

Удаление/добавление части массива -> метод splice()

Метод splice() меняет контент массива путем удаления существующих элементов и/или добавления новых. Используйте аккуратно, метод мутирует массив.

Полная документация MDN splice.

array.splice(start[, deleteCount[, item1[, item2[, ...]]]]) 

Параметры

Индекс start – откуда начинается изменение массива (изначально 0).

deleteCount – (необязательный параметр) целое число, указывающее, сколько элементов старого массива необходимо удалить.

item1, item2, … (необязательные параметры) – элементы, которые необходимо удалить из массива, начиная со start. Если элементы не заданы, splice() удалит только элементы из массива.

Возвращаемое значение

Массив удаленных элементов. Если удален 1 элемент, возвращается массив из одного элемента. Если элементы не удалены, возвращается пустой массив.

var months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at 1st index position
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'June']
months.splice(4, 1, 'May');
// replaces 1 element at 4th index
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'May']

Удаление последнего элемента из массива -> метод pop()

Метод pop() удаляет последний элемент из массива и возвращает его. Метод меняет длину массива.

var elements = ['Task 1', 'Task 2', 'Task 3'];

Все о массивах в JavaScript в 1 статье

Слияние двух массивов -> метод concat()

Метод concat() используется для слияния двух и более массивов. Метод не меняет существующие массивы и возвращает новый.

let array1 = ['a', 'b', 'c'];
let array2 = ['d', 'e', 'f'];
let merged = array1.concat(array2);
console.log(merged);
// expected output: Array ["a", "b", "c", "d", "e", "f"] 

Слияние двух массивов ES6 (оператор расширения)

let array1 = ['a', 'b', 'c'];
let array2 = ['d', 'e', 'f'];
let merged = [...array1, ...array2];
console.log(merged);
// expected output: Array ["a", "b", "c", "d", "e", "f"] 

Объединение массивов -> метод join()

Метод join() объединяет все элементы массива (или массивоподобного объекта) в строку и возвращает ее. Очень полезный метод.

var elements = ['Task 1', 'Task 2', 'Task 3'];
console.log(elements.join());
// expected output: Task 1,Task 2,Task 3
console.log(elements.join(''));
// expected output: Task 1Task 2Task3
console.log(elements.join('-'));
// expected output: Task 1-Task 2-Task 3

Вывод

Все о массивах в JavaScript в 1 статье

Перебор массива в цикле

Существуют разные способы перебора массива в цикле. Разберем простой пример.

Все о массивах в JavaScript в 1 статье

Перебор массива в цикле – цикл  forEach

Цикл forEach принимает в качестве параметра функцию (обычную или стрелочную) и дает доступ к отдельному элементу массива в виде параметра этой функции. Функция принимает 2 параметра: первый – массив элементов, второй – индекс.

projects.forEach((e) => { console.log(e);
});

Все о массивах в JavaScript в 1 статье

projects.forEach(function (e) { console.log(e);
});

Все о массивах в JavaScript в 1 статье

Как получить доступ к индексу в forEach. Ниже я использую стрелочную функцию, но способ работает и для ES5 функций.

projects.forEach((e, index) => { console.log(e, index);
});

Все о массивах в JavaScript в 1 статье

Поиск элементов в массиве – метод find

Метод find() возвращает значение первого элемента в массиве, который удовлетворяет функции тестирования. В противном случае возвращается undefined. Синтаксис.

callback - функция, которая будет выполняться на всех значениях массив, принимает 3 параметра

***** element - текущий обрабатываемый элемент в массиве

***** index (необязательно) – индекс текущего элемента

***** array (необязательно) – массив, над которым выполняется поиск.

thisArg (необязательно) – объект, который будет использоваться для this при выполнении колбека.

Возвращаемое значение

Если элемент прошел тест, значение в массиве, иначе undefined.

arr.find(callback[, thisArg])
var data = [51, 12, 8, 130, 44];
var found = data.find(function(element) { return element > 10;
});
console.log(found); // expected output: 51

Перебор массива – цикл for in

Цикл for…in работает только с перечисляемыми свойствами. Так как массивы перечисляемые, поэтому он работает с ними.

Цикл перебирает все перечисляемые свойства самого объекта и объектов, наследуемых от прототипа конструктора (свойства, расположенные ближе к объекту в цепочке прототипа, переписывают свойства прототипа).

Более подробно на MDN for in.

for(let index in projects) { console.log(projects[index]);
}

Все о массивах в JavaScript в 1 статье

Заметьте, что в коде сверху каждый раз в цикле создается переменная index.

Перебор массива в цикле – функция map

Функция map() позволяет трансформировать массив в новый объект и вернуть новый массив на основе переданной функции.

Это очень мощный метод в руках JS разработчика.

Заметка: map всегда возвращает одно и то же количество выводных данных, но он может изменить тип этих данных. Например, если массив содержит 5 элементов, map вернет 5 трансформированных элементов.

let num = [1,2,3,4,5];
let squared = num.map((value, index, origArr) => { return value * value;
});

Функция, передаваемая в map, принимает 3 параметра.

squared — новый возвращаемый массив

num — массив, на котором будет запускаться функция map

value — текущее обрабатываемое значение

index — текущий индекс обрабатываемого значения

origArr — оригинальный массив

Map() – пример 1 – простой

let num = [1,2,3,4,5];
let squared = num.map((e) => { return e * e;
});
console.log(squared);

В коде сверху мы пробегаем по всем элементам в массиве и создаем новый массив со значениями в квадрате. Вывод

Все о массивах в JavaScript в 1 статье

Map() – пример 2 – простая трансформация

Возьмем входной объектный литерал и трансформируем его в пару ключ/значение.

Например, возьмем массив ниже.

let projects = ['Learn Spanish', 'Learn Go', 'Code more']; 

И трансформируем его в пару ключ/значение, как показано ниже.

{ 0: "Learn Spanish", 1: "Learn Go", 2: "Code more"
}

Код верхней трансформации с выводом.

let newProjects = projects.map((project, index) => { return { [index]: project }
});
console.log(newProjects);

Все о массивах в JavaScript в 1 статье

Map() – пример 3 – возвращаемый поднабор данных

Разберем пример ниже

let tasks = [ { "name": "Learn Angular", "votes": [3,4,5,3] }, { "name": "Learn React", "votes": [4,4,5,3] },
]; 

Нам нужно вывести name от tasks. Реализация:

let taskTitles = tasks.map((task, index, origArray) => { return { name: task.name }
});
console.log(taskTitles); 

И вывод.

Все о массивах в JavaScript в 1 статье

Перебор массива в цикле – функция filter

Filter возвращает поднабор массива. Метод полезен, когда нужно найти записи в коллекции записей. Колбек функция для filter должна возвращать true или false. Значение true включает запись в новый массив, а false исключает запись из нового массива.

Возвращается новый массив. Разберем пример массива.

let tasks = [ { "name": "Learn Angular", "rating": 3 }, { "name": "Learn React", "rating": 5 }, { "name": "Learn Erlang", "rating": 3 }, { "name": "Learn Go", "rating": 5 },
]; 

Давайте с помощью filter найдем все tasks с rating 5. Код и результат.

let tasks5 = tasks.filter((task) => { return task.rating === 5;
});
console.log(tasks5); 

И вывод.

Все о массивах в JavaScript в 1 статье

В функции filter у нас всего 1 значение, поэтому ее можно укоротить до следующего вида:

tasks.filter(task => task.rating === 5); 

Заметка: функция filter не трансформирует вывод в новый массив.

Перебор массива в цикле – функция reduce

Функция reduce проходит в цикле по массиву и может вернуть уменьшенный набор. Это очень мощная функция. Мне кажется, мощнее других методов работы с массивами (хотя у каждого метода своя роль).

Метод reduce() (из MDN) применяет функцию к аккумулятору и каждому элементу в массиве (слева направо), чтобы уменьшить его до одного значения.

Reduce – простой пример 1

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer)); // expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15 

Заметка: при первом вызове колбека accumulator и currentValue могут быть одним из двух значений. Если в вызов reduce() передали initialValue, то accumulator будет равен initialValue, а currentValue будет равно первому значению в массиве. Если initialValue нет, то accumulator будет равен первому значению массива, а currentValue второму.

Мощь reduce() заключается в том, что с его помощью можно реализовать свои map(), find() и filter().

Использование reduce для разбиения данных на категории

Например, у вас есть структура данных ниже, которую вам нужно разбить на категории male и female.

let data = [ {name: "Raphel", gender: "male"}, {name: "Tom", gender: "male"}, {name: "Jerry", gender: "male"}, {name: "Dorry", gender: "female"}, {name: "Suzie", gender: "female"}, {name: "Dianna", gender: "female"}, {name: "Prem", gender: "male"},
]; 

Нам нужно, чтобы вывод был следующим:

{"female" : [ {name: "Dorry", gender:"female"}, {name: "Suzie", gender: "female"}, {name: "Dianna", gender: "female"}, ], "male" : [ {name: "Raphel", gender:"male"}, {name: "Tom", gender:"male"}, {name: "Jerry", gender:"male"}, {name: "Prem", gender:"male"}, ]
} 

Посмотрим код и поймем, как разбить данные на такие категории.

let genderwise = data.reduce((acc,item, index) => { acc[item.gender].push(item); return acc; }, {male: [], female:[]});
console.log(genderwise); 

Все о массивах в JavaScript в 1 статье

Важный момент в коде выше – функцию reduce можно инициализировать со стартовым аккумулятором любого типа. В примере сверху это объектный литерал.

{ male: [], female: []} 

Надеюсь, это точно демонстрирует мощь reduce.

Реализация кастомной функции map() с помощью reduce

function map(arr, fn) { return arr.reduce((acc, item) => [...acc, fn(item)], []);
} 

Сверху показана реализация кастомной функции map. В функцию сверху мы передаем пустой массив [] как первое значение для аккумулятора. Функция reduce возвращает новый массив со значениями из расширенного аккумулятора и добавляет результат выполнения колбек функции с текущим элементом.

Давайте посмотрим на использование и вывод.

Все о массивах в JavaScript в 1 статье

Реализация кастомной функции filter() с помощью reduce

Реализуем метод filter() с помощью reduce().

function filter (array, fn) { return arr.reduce(function (acc, item, index) { if (fn(item, index)) { acc.push(item); } return acc; },[]);
} 

Посмотрим, как использовать код выше и его вывод. Я мог бы переписать оригинальный Array.prototype.filter, но делаю так, чтобы не манипулировать встроенными методами.

Внутри кастомного фильтра выполняем функцию reduce и добавляем только те элементы к аккумулятору, которые совпадают с предикатом, который возвращает колбек в фильтр.

Все о массивах в JavaScript в 1 статье

Реализация функции foreach с помощью reduce

Разберем реализацию своей функции foreach.

function forEach(arr, fn) { arr.reduce((acc, item, index) => { item = fn(item, index); }, []);
} 

По сравнению с другими методами, реализация очень простая. Мы просто берем переданный массив, выполняем reduce и возвращаем текущий элемент, как результат выполнения колбека с текущим элементом и индексом.

Пример использования и вывод.

Все о массивах в JavaScript в 1 статье

Дыры в массивах

Дыры в массивах – это пустые элементы. Они могут появиться из-за ряда операций типа удаления или других операций, которые случайно оставили дыры.

Сейчас иметь дыры в массиве плохо с точки зрения производительности. Разберем пример.

let num = [1,2,3,4,5]; // No holes or gaps
delete num[2]; // Creates holes
console.log (num); [1, 2, empty, 4, 5] 

Не используйте delete на массиве, если не знаете точно, что делаете. Метод delete не меняет длину массива. Избежать дыр в массиве можно с помощью методов splice(), pop() или shift().

Изменение длины массива и дыр

Вы можете быстро изменить длину массива.

let num = [1,2,3,4,5]; // length = 5;
num.length = 3; // change length to 3
//The below logs outputs
// [1,2,3] -> The last two elements are deleted
console.log(num); 

Если теперь увеличить длину, образуется дыра.

let num = [1,2,3,4,5];
num.length = 10; // increase the length to 10
console.log(num); // See holes here 

Все о массивах в JavaScript в 1 статье

Автор: Rajesh Pillai

Источник: https://codeburst.io/

Редакция: Команда webformyself.