Распространенная проблема, с которой сталкиваются многие программисты, - это перебор перечислимого набора данных. Эти данные могут поступать в виде массивов, списков, карт или других объектов. К счастью, разработчики имеют в своем распоряжении множество инструментов, применимых именно к этой проблеме. В частности, язык JavaScript предоставляет разнообразный набор итерационных устройств. Ниже приводится краткое объяснение многих полезных операторов и методов JavaScript, применимых для циклического перебора массивов и объектов.

Пока цикл

Начнем с простой задачи. Задача - распечатать серию сообщений, хранящихся в массиве. Простой цикл while с использованием индекса массива может выполнить работу, как показано ниже.

messageArray = ["hello","how are you?",
                "how's the weather",
                "how's the family?",
                "Where do you live?"];
let index = 0;
while(index < messageArray.length){
  console.log(messageArray[index]);
  index += 1;
}
OUTPUT:
“hello”
“how are you?”
“how’s the weather”
“how’s the family?”
“Where do you live?”

Цикл while работает следующим образом:

  1. В начале каждой итерации программа оценивает условие
  2. Если условие истинно, т.е. переменная приращения меньше длины массива, цикл продолжает выполнение.
  3. Если условие ложно, выполнение цикла прекращается.
  4. В конце основного кода в теле цикла индекс увеличивается, и операция применяется к следующему элементу массива.

Это просто и работает. Однако ему не хватает элегантности. Это требует объявления переменной вне самого цикла, что открывает возможность проблем с областью видимости и изменения значений. Кроме того, отказ увеличить индекс приведет к бесконечному циклу.

Для петли

Для более автономного решения существует знаменитый цикл for.

messageArray = [“hello”,”how are you?”,
                ”how’s the weather”,
                ”how’s the family?”,
                ”Where do you live?”];
for(let i = 0;i < messageArray.length;i++){
   console.log(messageArray[i]);
}
OUTPUT:
“hello”
“how are you?”
“how’s the weather”
“how’s the family?”
“Where do you live?”

Цикл for работает следующим образом:

  1. Цикл начинается с трех операторов: инициализация переменной, условие и изменение значения переменной.
  2. На первой итерации переменная инициализируется нулем.
  3. Если выражение условия истинно, выполнение цикла продолжается. т.е. переменная приращения меньше длины массива.
  4. Если выражение условия оценивается как ложное, выполнение цикла завершается.
  5. Третий оператор увеличивает индексную переменную.
  6. Основной код цикла выполняется в каждом цикле.

Этот код работает так же хорошо и более компактен. Вся необходимая информация содержится в первой строке цикла с самодостаточной логикой. Однако у него есть свои недостатки. Задача, которую мы даем компьютеру, заключается в следующем: «перебрать массив и обработать каждый из его элементов».

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

для… из

Чтобы решить именно эту проблему, Javascript разработал цикл for..of. Давайте перепишем описанную выше задачу, используя ее.

for(let message of messageArray){
   console.log(message);
}
OUTPUT:
“hello”
“how are you?”
“how’s the weather”
“how’s the family?”
“Where do you live?”

for..ofloop - отличный инструмент, который во многих случаях превосходит предыдущие циклы. Он берет на себя большую часть рутинной реализации проблемы; позволяя программисту сосредоточиться на мышлении более высокого уровня. Однако он оставляет фактическое значение индекса вне цикла. К счастью, в этом случае мы можем просто вернуться к циклам while или for.

для каждого

Стоит упомянуть еще один инструмент для перебора циклов: forEach. forEach - это встроенный метод в JavaScript, который позволяет нам перебирать массив без дополнительной информации. Мне нравится этот метод, потому что он создан специально для такого типа задач и к тому же универсален. Базовый синтаксис метода следующий:

arr.forEach(callback(currentValue,index,array),thisArg)

  1. callback: функция обратного вызова, которая работает с каждым элементом массива.
  2. currentValue: текущий элемент в массиве, с которым работает обратный вызов.
  3. array: фактический массив, который forEach перебирает.
  4. thisArg: пользователь дает возможность указать аргумент this.

Давайте посмотрим, как применить forEach к этой проблеме.

messageArray.forEach(function(message){
   console.log(message);
   });

или с анонимной функцией…

messageArray.forEach(message => console.log(message));
OUTPUT:
“hello”
“how are you?”
“how’s the weather”
“how’s the family?”
“Where do you live?”

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

messageArray.forEach((message, index) => 
   console.log(`${index}. ${message}`));
OUTPUT:
“0. hello”
“1. how are you?”
“2. how’s the weather”
“3. how’s the family?”
“4. Where do you live?”

forEach - один из наиболее эффективных инструментов итераций цикла, имеющихся в распоряжении программиста JavaScript. Этот код скрывает почти всю реализацию цикла нижнего уровня, одновременно сжимая логику итерации цикла до одной строки. Однако одно предостережение. В отличие от циклов нижнего уровня, forEach не предоставляет способа преждевременного выхода из циклов с помощью оператора break, кроме выдачи ошибки.

ОБЪЕКТЫ

В JavaScript есть много полезных и универсальных инструментов для циклического перебора массивов. Однако массивы - не единственные итерируемые наборы данных, которые должен обрабатывать кодировщик. Кроме того, методы массива не подходят для других типов объектов с нецелочисленными ключами. По этой причине JavaScript предоставляет методы для перебора объектов.

для… в

Одним из наиболее распространенных и простых инструментов для перебора объектов является for…in. Это объектный эквивалент for…of. Он просто перебирает объект по именам свойств. Давайте посмотрим на пример ниже.

Допустим, нам нужно распечатать цены и количество различных товаров в магазине на основе их названий. Для этого мы можем использовать объект со свойствами цены и количества.

storeItems = {
   eggs: {price: 3.77, quantity: 30},
   milk: {price: 2.22, quantity: 23},
   butter: {price: 2.00, quantity: 22},
   carrots: {price: 3.00, quantity: 11},
   beef: {price: 6.18, quantity: 34},
   chicken: {price: 5.44, quantity: 34}
};

Используя цикл for..in, мы можем перебирать этот объект по имени свойства, чтобы получить доступ ко всем свойствам.

for(let item in storeItems){
   console.log(`${storeItems[item].quantity} ${item}s each cost
   ${storeItems[item].price}`);
}
OUTPUT:
“30 eggs each cost 3.77”
“23 milks each cost 2.22”
“22 butters each cost 2”
“11 carrots each cost 3”
“34 beefs each cost 6.18”
“34 chickens each cost 5.44”

Цикл for…in работает следующим образом:

  1. Цикл начинается с объявления переменной, представляющей имя свойства каждого элемента в объекте.
  2. Затем цикл перебирает все перечислимые свойства объекта.
  3. Код в теле цикла выполняется для каждого свойства объекта.
  4. После того, как последнее свойство достигнуто и обработано, цикл завершается.

Object.keys (myObj)

Еще один полезный инструмент итерации цикла объектов, который стоит изучить - Object.keys. Он работает аналогично for..in, по сути перемещая имена свойств объекта. Основное отличие состоит в том, что эта функция возвращает массив, элементы которого являются строками, соответствующими перечислимым свойствам, найденным непосредственно в объекте. Код выполняет итерацию по свойствам в том же порядке, как если бы это было сделано вручную. В приведенном ниже примере показано object.keys, примененное к предыдущему объекту.

Object.keys(storeItems).forEach(item =>  
  console.log(`${storeItems[item].quantity} ${item}s each cost 
  ${storeItems[item].price}`
));
OUTPUT:
“30 eggs each cost 3.77”
“23 milks each cost 2.22”
“22 butters each cost 2”
“11 carrots each cost 3”
“34 beefs each cost 6.18”
“34 chickens each cost 5.44”

Метод Object.keys работает следующим образом:

  1. Метод проходит по объекту, собирая все имена перечислимых свойств в объекте.
  2. Эти имена свойств объединены в массив.
  3. Теперь метод возвращает массив со всеми именами свойств объекта в строковой форме.
  4. Благодаря этому код может получить доступ ко всем свойствам объекта с помощью цикла, такого как forEach.
  5. Метод массива forEach просматривает массив и использует имена свойств для работы на основе каждого свойства объекта.

Приведенный выше код выполняет ту же работу, что и for..in, но немного более подробный. Однако у использования Object.keys перед for..in может быть как минимум несколько преимуществ. Во-первых, гораздо более вероятно, что свойства объекта будут перебираться в правильном порядке, определенном изначально. Во-вторых, наличие ключей объекта в виде массива имеет преимущества. Например, программист может найти количество свойств в объекте, найдя длину возвращенного массива.

Object.entries (myObj)

Подобно тому, как Object.keys, Object.entries возвращает массив. Однако Object.entries возвращает массив пар ключ-значение, чтобы обеспечить большую гибкость в реализации. Как и Object.keys, код перебирает свойства в том же порядке, что и вручную.
Давайте рассмотрим, как применяется этот метод ниже:

Object.entries(storeItems).forEach(item =>
   console.log(`${item[1].quantity} ${item[0]}s each cost
   ${item[1].price}`);
);
OUTPUT:
“30 eggs each cost 3.77”
“23 milks each cost 2.22”
“22 butters each cost 2”
“11 carrots each cost 3”
“34 beefs each cost 6.18”
“34 chickens each cost 5.44”

Приведенный выше код выполняет ту же работу, что и Object.keys. Основное отличие состоит в том, что этот метод дает прямой доступ как к именам свойств, так и к самим свойствам.

Ключевые выводы

  • JavaScript предоставляет широкий спектр инструментов для применения ко многим задачам, требующим циклического перебора перечислимого набора данных. Эта статья ни в коем случае не является исчерпывающим списком.
  • Хотя это и не идеально, операторы цикла общего назначения, такие как while и for, могут использоваться для перебора массивов с использованием их индексов.
  • В JavaScript есть множество встроенных инструментов, разработанных специально для задачи перебора перечислимых наборов данных, как массивов, так и объектов, включая for…of, for…in, forEach, Object.keys и object .entries.
  • Как разработчик, вы должны выбрать, какой инструмент применить, в зависимости от решаемой проблемы и ее контекста.