Рубріки: Теория

Массивы в JavaScript: самые полезные методы с примерами

Павло Бєлавін

Если вы пишете на JavaScript и хотите улучшить свои навыки, то должны хорошо разбираться с самыми ходовыми методами массивов в ES5 и ES6+. С помощью этих методов кодировать будет проще, сам код будет красивей и понятней, а работа с массивами станет эффективней. Обзор самых полезных методов массивов с примерами опубликовал на сайте freeCodeCamp Йогеш Чаван (Yogesh Chavan).

Метод forEach

Синтаксис метода forEach:

Array.forEach(callback(currentValue [, index [, array]])[, thisArg]);

Метод forEach выполняет предоставленную функцию один раз для каждого элемента массива.

Смотрите код ниже:

const months = ['January', 'February', 'March', 'April'];

months.forEach(function(month) {
  console.log(month);
});

/* output

January
February
March
April

*/

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

Нужно помнить, что метод forEach ничего не возвращает. Взгляните на код ниже:

const months = ['January', 'February', 'March', 'April'];
const returnedValue = months.forEach(function (month) {
  return month;
});

console.log('returnedValue: ', returnedValue); // undefined

Важно: forEach используется только, чтобы перебрать все элементы массива и выполнить обработку или логирование. Он ничего не возвращает, даже если явно возвращать значение из функции обратного вызова (то есть возвращает значение undefined в примере выше).

В примерах выше использовался только первый парметр функции обратного вызова. Но она принимает еще два параметра:

  • index — индекс текущего элемента, по которому осуществляется проход
  • array — сам массив, по которому осуществляется проход
const months = ['January', 'February', 'March', 'April'];

months.forEach(function(month, index, array) {
  console.log(month, index, array);
});

/* output

January 0 ["January", "February", "March", "April"]
February 1 ["January", "February", "March", "April"]
March 2 ["January", "February", "March", "April"]
April 3 ["January", "February", "March", "April"]

*/

Преимущества использования forEach вместо for loop:

  • код получается короче и понятней;
  • не нужно следить за тем, сколько элементов в массиве, что помогает избежать создания лишней переменной-счетчика;
  • упрощается отладка кода, поскольку нет дополнительных переменных для перебора массива;
  • цикл forEach автоматически останавливается, когда все элементы массива проитерированы.

Поддержка браузеров:

  • Все современные браузеры и IE версии 9.0 и выше;
  • Microsoft Edge версии 12 и выше.

Метод map

Метод map — самый полезный и популярный.

Синтаксис метода:

Array.map(function callback(currentValue[, index[, array]]) {
    // Return element for new_array
}[, thisArg])

Метод map выполняет предоставленную функцию один раз для каждого элемента массива и возвращает новый измененный масив.

Взгляните на код ниже:

const months = ['January', 'February', 'March', 'April'];
const transformedArray = months.map(function (month) {
  return month.toUpperCase();
});

console.log(transformedArray); // ["JANUARY", "FEBRUARY", "MARCH", "APRIL"]

В коде выше, внутри функции обратного вызова, каждый элемент конвертируется в верхний регистр и возвращается.

Метод map позволяет избежать создания отдельного массива converted для хранения конвертированных элементов. То есть сэкономить память и получить более элегантный код, используя массив map. Вот так: 

const months = ['January', 'February', 'March', 'April'];

console.log(months.map(function (month) {
  return month.toUpperCase();
})); // ["JANUARY", "FEBRUARY", "MARCH", "APRIL"]

Обратите внимание, что метод map возвращает новый массив такой же длины, что оригинальный массив. 

Разница между методами forEach и map в том, что forEach используется только для перебора и ничего не возвращает, а метод map возвращает новый массив такой же длины, что и оригинальный. Кроме того, он не изменяет оригинальный массив, а возвращает новый.

Взгляните на код ниже:

const users = [
  {
    first_name: 'Mike',
    last_name: 'Sheridan'
  },
  {
    first_name: 'Tim',
    last_name: 'Lee'
  },
  {
    first_name: 'John',
    last_name: 'Carte'
  }
];

const usersList = users.map(function (user) {
  return user.first_name + ' ' + user.last_name;
});

console.log(usersList); // ["Mike Sheridan", "Tim Lee", "John Carte"]

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

В коде выше используется оператор + для объединения двух значений. Однако, чаще используют синтаксис шаблонных литералов ES6, как показано ниже:

const users = [
  {
    first_name: 'Mike',
    last_name: 'Sheridan'
  },
  {
    first_name: 'Tim',
    last_name: 'Lee'
  },
  {
    first_name: 'John',
    last_name: 'Carte'
  }
];

const usersList = users.map(function (user) {
  return `${user.first_name} ${user.last_name}`;
});

console.log(usersList); // ["Mike Sheridan", "Tim Lee", "John Carte"]

Метод массивов map также полезен, если нужно получить только определенные данные из масива: 

const users = [
  {
    first_name: 'Mike',
    last_name: 'Sheridan',
    age: 30
  },
  {
    first_name: 'Tim',
    last_name: 'Lee',
    age: 45
  },
  {
    first_name: 'John',
    last_name: 'Carte',
    age: 25
  }
];

const surnames = users.map(function (user) {
  return user.last_name;
});

console.log(surnames); // ["Sheridan", "Lee", "Carte"]

В коде выше автор извлекает только фамилии каждого пользователя и сохраняет их в массиве. 

С помощью map можно сгенерировать массив с динамическим контентом, как показано ниже: 

const users = [
  {
    first_name: 'Mike',
    location: 'London'
  },
  {
    first_name: 'Tim',
    location: 'US'
  },
  {
    first_name: 'John',
    location: 'Australia'
  }
];

const usersList = users.map(function (user) {
  return `${user.first_name} lives in ${user.location}`;
});

console.log(usersList); // ["Mike lives in London", "Tim lives in US", "John lives in Australia"]

Обратите внимание, что в коде выше оригинальный массив users не меняется, а создается новый массив с динамическим контентом, потому что map всегда взвращает новый массив.

Преимущества метода map:

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

Поддержка браузеров:

  • все современные браузеры и IE версии 9.0 и выше
  • Microsoft Edge версии 12.0 и выше.

Метод find

Синтаксис метода find выглядит следующим образом:

Array.find(callback(element[, index[, array]])[, thisArg])

Метод find возвращает значение первого элемента в массиве, которое соответствует указанному условию. 

Метод find принимает функцию обратного вызова как первый аргумент и выполняет ее для каждого элемента массива. Значение каждого элемента массива передается функции обратного вызова. 

Предположим, что есть список сотрудников:

const employees = [
 { name: "David Carlson", age: 30 },
 { name: "John Cena", age: 34 },
 { name: "Mike Sheridan", age: 25 },
 { name: "John Carte", age: 50 }
];

Мы хотим получить запись дя работника с именем John. В этом случае можно использовать метод find, как показано ниже:

const employee = employees.find(function (employee) {
  return employee.name.indexOf('John') > -1;
});

console.log(employee); // { name: "John Cena", age: 34 }

Хотя в списке есть John Carte, метод find остановится, когда найдет первое совпадение, то есть возвратит объект с именем John Carte.

Как видите, использование normal for loop делает код громоздким и запутаным. Но метод find позволяет сделать тот же код понятней. 

Преимущества метода find:

  • позволяет быстро найти любой элемент и не писать при этом много кода;
  • прекращает перебор элементов, как только находит совпадение, и дополнительный оператор break становится не нужен.

Поддержка браузеров:

  • Все современные браузеры, кроме IE;
  • Microsoft Edge версии 12 и выше.

Метод findIndex

Синтаксис метода findIndex:

Array.findIndex(callback(element[, index[, array]])[, thisArg])

Метод findIndex возвращает индекс первого элемента в массиве, который соответствует указанному условию. В противном случае, он возвращает -1, указывая, что ни один элемент не удовлетворяет условию. 

const employees = [
  { name: 'David Carlson', age: 30 },
  { name: 'John Cena', age: 34 },
  { name: 'Mike Sheridan', age: 25 },
  { name: 'John Carte', age: 50 }
];

const index = employees.findIndex(function (employee) {
  return employee.name.indexOf('John') > -1;
});

console.log(index); // 1

Мы получаем  на выходе 1 — индекс первого объекта с именем John. Обратите внимание, что индекс начинается с ноля.

Преимущества метода findIndex:

  • позволяет быстро найти индекс элемента без необходимости писать кучу кода;
  • прекращается, как только находит совпадение, поэтому необходимость в дополнительном операторе break отпадает;
  • индекс можно найти с также помощью метода find, но findIndex поможет упростить этот процесс и избежать создания дополнительных переменных для хранения индекса.

Поддержка браузеров:

  • все современные браузеры, кроме IE;
  • Microsoft Edge версии 12 и выше.

Метод filter

Синтаксис метода filter (): 

Array.filter(callback(element[, index[, array]])[, thisArg])

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

const employees = [
  { name: 'David Carlson', age: 30 },
  { name: 'John Cena', age: 34 },
  { name: 'Mike Sheridan', age: 25 },
  { name: 'John Carte', age: 50 }
];

const employee = employees.filter(function (employee) {
  return employee.name.indexOf('John') > -1;
});

console.log(employee); // [ { name: "John Cena", age: 34 }, { name: "John Carte", age: 50 }]

Из кода выше видно, что filter позволяет найти все элементы массива, которые соотвествуют заданному условию.

Метод filter не останавливается, когда находит конкретное совпадение, а осуществляет перебор всех элементов массива, которые соотвествуют условию. Затем возвращает все соответствующие элементы из массива.

Главное различие между find и filter в том, что find возвращает лишь первый соотвествующий элемент массива, а filter возвращает все соотвествующие элементы. 

Обратите внимание, что метод filter всегда возвращает массив. Если ни один элемент не соотвествует указанному условию, возвращается пустой массив.

Преимущества метода filter:

  • позволяет быстро найти все соответствующие элементы из массива;
  • всегда возвращает массив, даже если нет совпадений, поэтому не нужно писать дополнительные условия if;
  • не нужно создавать дополнительную переменную для хранения отсортированных элементов.

Поддержка браузеров:

  • Все современные браузеры и IE версии 9.0 и выше;
  • Microsoft Edge версии 12 и выше.

Метод every

Синтаксис метода every:

Array.every(callback(element[, index[, array]])[, thisArg])

Метод every проверяет, все ли элементы массива соотвествуют заданным условиям и возвращает булевое значение true или false.

Предположим, что есть массив чисел и мы хотим проверить, все ли элементы массива являются положительными числами. В этом случае можно использовать метод every.

let numbers = [10, -30, 20, 50];

let allPositive = numbers.every(function (number) {
  return number > 0;
});
console.log(allPositive); // false 

numbers = [10, 30, 20, 50];

allPositive = numbers.every(function (number) {
  return number > 0;
});
console.log(allPositive); // true

Представим, что существует регистрационная форма и мы хотим проверить, все ли требуемые поля введены до того как отправить форму. Можно использовать метод every, чтобы проверить значение каждого поля.

window.onload = function () {
  const form = document.getElementById('registration_form');
  form.addEventListener('submit', function (event) {
    event.preventDefault();
    const fields = ['first_name', 'last_name', 'email', 'city'];
    const allFieldsEntered = fields.every(function (fieldId) {
      return document.getElementById(fieldId).value.trim() !== '';
    });

    if (allFieldsEntered) {
      console.log('All the fields are entered');
      // All the field values are entered, submit the form
    } else {
      alert('Please, fill out all the field values.');
    }
  });
};

Здесь, внутри функции обратного вызова метода every, мы проверяем, не является ли значение каждого поля пустым и возвращает ли оно булевое значение. 

В коде выше метод every возвращает true, если для всех  элементов в массиве fields функция обратного вызова возвращает значение true. 

Если функция обратного вызова возвращает значение false для любого из элементов в массиве fields, метод every в результате возвращает false. 

Преимущества метода every:

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

Поддержка браузеров:

  • Все современные браузеры и IE версии 9.0 и выше;
  • Microsoft Edge версии 12 и выше.

Метод reduce

Синтаксис метода reduce:

Array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

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

Обратите внимание, что метод reduce весгда возвращает единственное значение. Это может быть объект, число, строка, массив и так далее. Все зависит от того, что должно генерировать возвращаемое значение метода reduce, но это всега единственное значение.  

Предположим, вы хотите найти сумму всех чисел в массиве. Для этого подойдет метод reduce. 

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce(function(accumulator, number) {
  return accumulator + number; 
}, 0);

console.log(sum); // 15

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

Аккумулятор будет содержать initialValue, которое используется для массива. initialValue решает, какой тип данных возвращает метод reduce.  

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

В коде выше initialValue для аккумулятора — 0. Таким образом, во время первого выполнения функции обратного вызова, аккумулятор + число = 0+1 = 1 и возвращается значение 1. Во время следующего выполнения функции обратного вызова, аккумулятор + число равно 1+2 = 3 (1 — это предыдущее значение, возвращенное во время последней итерации, а 2 — следующий элемент из массива) .

Во время следующего выполнения функции обратного вызова, аккумулятор + число равно 3+3 = 6 (первое число 3 — предыдущее значение, возвращенное в время последней итерации, а следующая 3 — следующий элемент из массива) и так далее, пока все элементы массива numbers не будут проитерированы. 

Аккумулятор будет хранить значение последней операции как статическую переменную.  

В коде выше начальное значение (initialValue) 0 не является необходимым, потому что все элемены массива — целые числа.  

Код ниже также подойдет: 

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce(function (accumulator, number) {
  return accumulator + number;
});

console.log(sum); // 15

Аккумулятор будет содержать первый элемент массива, а число будет содержать следующий элемент массива (1 + 2 = 3 во время первой итерации, а во время следующей: 3 + 3 = 6 и так далее).

Всегда лучше обозначить initialValue аккумулятора, поскольку так легче понять, что возвращает метод reduce, и получить правильный тип данных обратно.

Взгляните на код ниже:

const numbers = [1, 2, 3, 4, 5];

const doublesSum = numbers.reduce(function (accumulator, number) {
  return accumulator + number * 2;
}, 10);

console.log(doublesSum); // 40

В данном случае каждый элемент массива умножается на 2. Аккумулятор получил initialValue 10, так что 10 будет добавляться к финальной сумме: 

[1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2] = [2, 4, 6, 8, 10] = 30 + 10 = 40

Предположим, существует массив объектов с координатами x и y нужно получить сумму координат x. Для этого можно использовать метод reduce.

const coordinates = [
  { x: 1, y: 2 }, 
  { x: 2, y: 3 }, 
  { x: 3, y: 4 }
];

const sum = coordinates.reduce(function (accumulator, currentValue) {
    return accumulator + currentValue.x;
}, 0);

console.log(sum); // 6

Преимущества метода reduce:

  • позволяет сгенерировать любой тип простых или сложных данных на основе массива;
  • запоминает предварительно возвращенные данные из цикла и помогает избежать создания глобальной переменной для хранения предыдущего значения.

Поддержка браузеров:

  • Все современные браузеры и IE версии 9.0 и выше;
  • Microsoft Edge версии 12 и выше.

Оригинальный текст перевела Ольга Наконечна.

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023