Циклы Javascript: for vs forEach vs for.. in vs for.. of
В Javascript есть довольно много способов перебора массива элементов или любого другого итеративного элемента в Javascript. Возможно, вы их видели:
arr.forEach()
for(let item of arr)
for(let item in arr)
for(let item = 0; item < arr.length; ++item)
Может показаться, что существует множество способов добиться одной и той же цели, но все они имеют свои нюансы. Чтобы любой из них работал, рассматриваемый элемент также должен быть итерируемым. Поэтому, хотя они будут работать с такими вещами, как Map, Set и Arrays, они не будут работать с объектами. Строки также являются итерируемыми.
Поскольку существует так много способов, может возникнуть путаница, когда использовать forEach
, in
или of
в Javascript. Сегодня давайте подробно разберемся, что делает каждый из них и когда их использовать.
Метод forEach
forEach
- это инструмент, к которому многие обращаются, потому что с лингвистической точки зрения он имеет смысл. arr.forEach
звучит правильно, и он предоставляет простую функцию обратного вызова, позволяющую делать все, что мы хотим, с каждым элементом в итеративном виде, таком как массив:
let x = [ 1, 2, 3, 4, 5 ];
x.forEach((item, index) => {
x[index] += 1;
});
console.log(x); // [ 2, 3, 4, 5, 6 ];
Однако forEach
метод - это означает, что он появляется только для определенных типов данных в Javascript. Например, все Array
имеют метод forEach
, как и Map
и Set
, но, несмотря на то, что они являются итеративными, String
этого не делают. Примечательно, что элементы DOM до недавнего времени не имели forEach. Таким образом, пока он надежно доступен во многих различных обстоятельствах. Это также намного медленнее, чем обычный старый цикл for
.
Кроме того, forEach
на самом деле не работает с асинхронными методами, такими как await
или promises
. В обстоятельствах, когда вам нужно использовать промисы или await
, лучше избегать этого и вместо этого использовать циклы for
.
Хотя forEach
, безусловно, является простым способом перебора массива, он не всегда является лучшим.
Использование циклов for для итераций
Существует три типа циклов for
для выполнения над итеративными объектами в Javascript:
for(let item of arr)
for(let item in arr)
for(let item = 0; item < arr.length; ++item)
Для тех, кто новичок в этом языке, синтаксис может показаться довольно запутанным. Когда Javascript только начинался, исходный цикл for
, который все использовали, был последним из перечисленных выше:
let x = [ 1, 2, 3, 4, 5 ];
for(let i = 0; i < x.length; ++i) {
console.log(x[i]); // 1.. 2.. 3.. 4.. 5
}
Это простой и понятный способ доступа к индексу массива. Здесь i
начинается с 0
и увеличивается для каждого элемента в массиве x
. Следовательно, i
надежно представляет индекс для каждого элемента, и, таким образом, запись x[i]
позволит нам что-то сделать с каждым элементом в массиве.
С тех пор были введены два новых типа цикла for
- in
и of
.
in vs of в Javascript для циклов
Лучший способ понять циклы in
и of
в Javascript for
заключается в том, что in
- это упрощение цикла for
, который мы только что рассмотрели. Это более простой способ получить доступ к индексу в массиве.
Между тем, of
- это простой способ представления самого элемента массива. Давайте рассмотрим краткий пример. Здесь мы получаем индекс каждого элемента в нашем массиве, используя in
:
let x = [ 5, 10, 15, 20, 25, 30 ];
for(let i in x) {
console.log(i); // 0.. 1.. 2.. 3.. 4.. 5
}
Между тем, если мы используем of
, то получаем фактическое значение элемента массива:
let x = [ 5, 10, 15, 20, 25, 30 ];
for(let i of x) {
console.log(i); // 5.. 10.. 15.. 20.. 25.. 30
}
Таким образом, в то время как in
в основном упрощает for(let i = 0; i < x.length; ++i)
, of
фактически дает нам новую функциональность для доступа к самому содержимому массива. Это может быть особенно полезно, если у нас есть объекты в наших массивах:
let x = [ { name: "John" }, { name: "Jacob" }, { name: "Jingleheimer" }, { name: "Schmidt" }]
for(let item of x) {
console.log(item.name); // John.. Jacob.. Jingleheimer.. Schmidt
}
Следует также отметить, что для других итеративных объектов, таких как Map
и Set
, for.. of
вернет массив как ключа, так и значения, в то время как in
не будет работать. Например:
let myMap = new Map();
myMap.set('x', 5);
for(let x of myMap) {
console.log(x); // [ 'x', 5 ]
}
for(let x in myMap) {
console.log(x); // does not console log anything
}
Итерация по объектам
Хотя сами объекты не являются итеративными в Javascript, их можно преобразовать в итеративные объекты с помощью Object.keys()
или Object.values()
. Это преобразует объект в массив либо его ключей, либо значений, которые затем могут быть повторены по:
let obj = { name: "John", secondName: "Jacob", age: 154 };
let iterableKeys = Object.keys(obj);
for(let item of iterableKeys) {
console.log(item); // name.. secondName.. age
}
Вывод
Это касается всего, что вам нужно знать. В итоге:
forEach
- это метод, который привязан к большинству итеративных элементов в Javascript, за некоторыми исключениями. Он основан на обратном вызове, обычно не работает с обещаниями и работает медленнее, чем традиционный цикл for.- циклы
for
доступны для каждого итеративного объекта, и раньшеfor(let i = 0; i < x.length; ++i)
был единственным форматом, который кто-либо использовал. for.. in
был введен для упрощенияfor(let i = 0; i < x.length; ++i)
доfor(let i in x)
.- Наконец, мы получили возможность получать доступ к значениям каждого элемента в итерации, а не только к ключу, используя
for.. of
.
Надеюсь, вам понравилось это руководство, и у вас есть лучшее представление о том, когда использовать in
, forEach
и of
в Javascript.