For

Пустые элементы

Массивы JavaScript допускают пустые элементы. Массив ниже синтаксически верный и имеет длину 3 элемента:

const arr = ;

arr.length; // 3

Что еще более запутывает, так это то, что циклические конструкции трактуют иначе, чем . Ниже показано, как четыре циклических конструкции обрабатывают с пустым элементом. for/in и for/each пропускают пустой элемент, for и for/of — нет.

// Prints "a, undefined, c"
for (let i = 0; i < arr.length; ++i) {
  console.log(arr);
}

// Prints "a, c"
arr.forEach(v => console.log(v));

// Prints "a, c"
for (let i in arr) {
  console.log(arr);
}

// Prints "a, undefined, c"
for (const v of arr) {
  console.log(v);
}

Если вам интересно, все 4 конструкции выведут «a, undefined, c» для .

Есть еще один способ добавить пустой элемент в массив:

// Equivalent to ``
const arr = ;
arr = 'e';

forEach() и for/in пропускают пустые элементы в массиве, for и for/of — нет. Поведение forEach() может вызвать проблемы, однако можно заметить, что дыры в массивах JavaScript, как правило, встречаются редко, поскольку они не поддерживаются в JSON:

$ node
> JSON.parse('{"arr":}')
{ arr:  }
> JSON.parse('{"arr":}')
{ arr:  }
> JSON.parse('{"arr":}')
SyntaxError: Unexpected token , in JSON at position 12

Таким образом, вам не нужно особо беспокоиться о дырах в пользовательских данных, если вы не предоставите своим пользователям доступ ко всей среде выполнения JavaScript.

Вывод: for/in и forEach() не реагируют на пустые элементы, также известные как «дыры», в массиве. Редко есть какая-либо причина рассматривать дыры как особый случай, а не рассматривать индекс как значение undefined. Если вы допускаете наличие дыр, ниже приведен пример файла .eslintrc.yml, который запрещает вызов forEach().

parserOptions:
  ecmaVersion: 2018
rules:
  no-restricted-syntax:
    - error
    - selector: CallExpression
      message: Do not use `forEach()`, use `for/of` instead

JavaScript

JS Массивы
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()

JS Булевы
constructor
prototype
toString()
valueOf()

JS Классы
constructor()
extends
static
super

JS Даты
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()

JS Ошибка
name
message

JS Булевы
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()

JS JSON
parse()
stringify()

JS Математика
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
cos()
cosh()
E
exp()
floor()
LN2
LN10
log()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()

JS Числа
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()

JS ОператорыJS Рег.Выражения
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()

(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx

JS Заявления
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while

JS Строки
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()

reduce/reduceRight

Метод «arr.reduce(callback)» используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата.

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

Метод используется для вычисления на основе массива какого-либо единого значения, иначе говорят «для свёртки массива». Чуть далее мы разберём пример для вычисления суммы.

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

Аргументы функции :

  • – последний результат вызова функции, он же «промежуточный результат».
  • – текущий элемент массива, элементы перебираются по очереди слева-направо.
  • – номер текущего элемента.
  • – обрабатываемый массив.

Кроме , методу можно передать «начальное значение» – аргумент . Если он есть, то на первом вызове значение будет равно , а если у нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.

Проще всего понять работу метода на примере.

Например, в качестве «свёртки» мы хотим получить сумму всех элементов массива.

Вот решение в одну строку:

Разберём, что в нём происходит.

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

Сначала анонимная функция вызывается с этим начальным значением и первым элементом массива, результат запоминается и передаётся в следующий вызов, уже со вторым аргументом массива, затем новое значение участвует в вычислениях с третьим аргументом и так далее.

Поток вычислений получается такой

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

результат
первый вызов
второй вызов
третий вызов
четвёртый вызов
пятый вызов

Как видно, результат предыдущего вызова передаётся в первый аргумент следующего.

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

Посмотрим, что будет, если не указать в вызове :

Результат – точно такой же! Это потому, что при отсутствии в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.

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

Метод arr.reduceRight работает аналогично, но идёт по массиву справа-налево.

For Each: Basic Examples

These examples will demonstrate how to set up For Each loops to loop through different types of objects.

Loop Through Cells

This procedure will loop through each cell in range A1:A10, setting the cell to it’s right equal to itself.

1
2
3
4
5
6
7
8

SubForEachCell()

DimCell AsRange

ForEachCell InSheets(«Sheet1»).Range(«A1:A10»)

Cell.Offset(,1).value=Cell.value

NextCell

EndSub

Loop Through Sheets

This procedure will loop through each sheet in a Workbook, unhiding each sheet.

1
2
3
4
5
6
7
8

SubForEachSheets()

Dimws AsWorksheet

ForEachws InSheets

ws.Visible=True

NextSheet

EndSub

Loop Through Workbooks

This procedure will loop through each workbook, closing each one.

1
2
3
4
5
6
7
8

SubForEachWorkbooks()

Dimwb AsWorkbook

ForEachwb InWorkbooks

wb.Close

Nextwb

EndSub

Loop Through Shapes

This procedure will loop through each shape in Sheet1, deleting each one.

1
2
3
4
5
6
7
8

SubForEachShape()

DimShp AsShape

ForEachShp InSheets(«Sheet1»).Shapes

Shp.Delete

NextShp

EndSub

Loop Through Charts

This procedure will loop through each Chart in Sheet1, deleting each one.

1
2
3
4
5
6
7
8

SubForEachCharts()

Dimcht AsChartObject

ForEachcht InSheets(«Sheet1»).ChartObjects

cht.Delete

Nextcht

EndSub

Loop Through PivotTables

This procedure will loop through each PivotTable in Sheet1, clearing each one

1
2
3
4
5
6
7
8

SubForEachPivotTables()

Dimpvt AsPivotTable

ForEachpvt InSheets(«Sheet1»).PivotTables

pvt.ClearTable

Nextpvt

EndSub

Loop Through Tables

This procedure will loop through each Table in Sheet1, deleting each one.

1
2
3
4
5
6
7
8

SubForEachTables()

Dimtbl AsListObject

ForEachtbl InSheets(«Sheet1»).ListObjects

tbl.Delete

Nexttbl

EndSub

Loop Through Items in Array

This procedure will loop through each item in an Array, display each value in a msgbox,

1
2
3
4
5
6
7
8
9
10

SubForEachItemInArray()

DimarrValue AsVariant

DimItem AsVariant

arrValue=Array(«Item 1″,»Item 2″,»Item 3»)

ForEachItem InarrValue

MsgBox Item

NextItem

EndSub

Loop Through Numbers

This procedure will loop through each number in an Array, display each value in a msgbox,

1
2
3
4
5
6
7
8
9
10
11
12
13

SubForEachNumberInNumbers()

DimarrNumber(1To3)AsInteger

Dimnum AsVariant

arrNumber(1)=10

arrNumber(2)=20

arrNumber(3)=30

ForEachnum InarrNumber

Msgbox Num

Nextnum

EndSub

Компоненты цикла For… Next

Компонент Описание
counter Обязательный атрибут. Числовая переменная, выполняющая роль счетчика, которую еще называют управляющей переменной цикла.
start Обязательный атрибут. Числовое выражение, задающее начальное значение счетчика.
end Обязательный атрибут. Числовое выражение, задающее конечное значение счетчика.
Step* Необязательный атрибут. Оператор, указывающий, что будет задан шаг цикла.
step Необязательный атрибут. Числовое выражение, задающее шаг цикла. Может быть как положительным, так и отрицательным.
statements Необязательный** атрибут. Операторы вашего кода.
Exit For Необязательный атрибут. Оператор выхода из цикла до его окончания.
Next Здесь counter – необязательный атрибут. Это то же самое имя управляющей переменной цикла, которое можно здесь не указывать.

*Если атрибут Step отсутствует, цикл For… Next выполняется с шагом по умолчанию, равному 1.

**Если не использовать в цикле свой код, смысл применения цикла теряется.

Пример с использованием Map

Мы уже видели вышеупомянутую программу для перебора всех записей HashMap и выполнения действия.

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

HashMap<String, Integer> map = new HashMap<>();
    
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

//1. Map entries
Consumer<Map.Entry<String, Integer>> action = System.out::println;

map.entrySet().forEach(action);

//2. Map keys
Consumer<String> actionOnKeys = System.out::println;

map.keySet().forEach(actionOnKeys);

//3. Map values
Consumer<Integer> actionOnValues = System.out::println;

map.values().forEach(actionOnValues);

Программа вывода.

A=1
B=2
C=3

A
B
C

1
2
3

» Using Expressions in for_each

The meta-argument accepts map or set expressions.
However, unlike most arguments, the value must be known
before Terraform performs any remote resource actions. This means
can’t refer to any resource attributes that aren’t known until after a
configuration is applied (such as a unique ID generated by the remote API when
an object is created).

The value must be a map or set with one element per desired
resource instance. When providing a set, you must use an expression that
explicitly returns a set value, like the
function; to prevent unwanted surprises during conversion, the
argument does not implicitly convert lists or tuples to sets.
If you need to declare resource instances based on a nested
data structure or combinations of elements from multiple data structures you
can use Terraform expressions and functions to derive a suitable value.
For example:

  • Transform a multi-level nested structure into a flat list by
    .
  • Produce an exhaustive list of combinations of elements from two or more
    collections by
    .

Chaining Between Resources

Because a resource using appears as a map of objects when used in
expressions elsewhere, you can directly use one resource as the
of another in situations where there is a one-to-one relationship between
two sets of objects.

For example, in AWS an object is commonly associated with a number
of other objects that provide additional services to that VPC, such as an
«internet gateway». If you are declaring multiple VPC instances using
then you can chain that into another resource to declare an
internet gateway for each VPC:

This chaining pattern explicitly and concisely declares the relationship
between the internet gateway instances and the VPC instances, which tells
Terraform to expect the instance keys for both to always change together,
and typically also makes the configuration easier to understand for human
maintainers.

Еще один пример

Вот пример первой программы из начала этого урока, но уже с использованием цикла foreach:

#include <iostream>

int main()
{
const int numStudents = 7;
int scores = { 45, 87, 55, 68, 80, 90, 58};
int maxScore = 0; // отслеживаем индекс наибольшего score (значения)
for (const auto &score: scores) // итерация по массиву, присваиваем каждое значение массива поочередно переменной score
if (score > maxScore)
maxScore = score;

std::cout << «The best score was » << maxScore << ‘\n’;

return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include <iostream>

intmain()

{

constintnumStudents=7;

intscoresnumStudents={45,87,55,68,80,90,58};

intmaxScore=;// отслеживаем индекс наибольшего score (значения)

for(constauto&scorescores)// итерация по массиву, присваиваем каждое значение массива поочередно переменной score

if(score>maxScore)

maxScore=score;

std::cout<<«The best score was «<<maxScore<<‘\n’;

return;

}

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

Цикл типа For

Выделяют несколько отдельных типов цикла For. Существует тип For … Next и For Each.

For … Next

Цикл For … Next опирается на переменную, которая увеличивается по окончании каждой итерации в определенном диапазоне. И каждый раз происходит выполнение определенного кода. Проще всего изобразить принцип работы цикла этого типа на легком фрагменте кода.

For i = 1 To 10

    Total = Total + iArray(i)

Next i

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

Здесь не указан размер шага, поэтому циклом используется стандартный размер 1. Выполняется такое количество итераций, которое позволяет сделать так, чтобы значение прошло от 1 до 10. Но если потребуется использовать разные размеры шагов, необходимо использовать слово Step. Приведем пример для наглядности.

For d = 0 To 10 Step 0.1

    dTotal = dTotal + d

Next d

В описанном варианте цикла определенный размер шага – 0,1, поэтому значение переменной d изменяется по числовому ряду 0.0, 0.1, 0,2 и так далее, пока значение переменной не достигнет 10.

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

For i = 10 To 1 Step -1

    iArray(i) = i

Next i

В данном примере кода указан размер шага -1. Следовательно, числовой ряд соответствующей переменной будет следующим: 10, 9, 8 – вплоть до единицы.

Цикл For Each

Цикл For Each аналогичен For Next, за исключением того, что последний проходит по числовому ряду значений, а For Each осуществляет требуемую последовательность действий для всех объектов, принадлежащих к заданной группе. Например, следующий код показывает, как пользователь мог бы применить цикл For Each.

Dim wSheet As Worksheet

For Each wSheet in Worksheets

    MsgBox “Found Worksheet: ” & wSheet.Name

Next wSheet

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

Конструкция Exit For

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

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

Рассмотрим еще один пример, который хорошо отображает работу оператора Exit For. Здесь цикл анализирует 100 объектов, интерпретатор сравнивает каждый из них со значением переменной dValue1s. Если оно равно dVal1, то цикл завершается.

For i = 1 To 100

If dValues1(i) = dVal1 Then

indexVal = i

Exit For

End If

Next i

Async/Await и генераторы

Другой крайний случай с forEach() — это то, что он не совсем правильно работает с async/await или генераторами. Если ваш callback forEach() является синхронным, то это не имеет значения, но вы не сможете использовать await внутри callback forEach ():

async function run() {
  const arr = ;
  arr.forEach(el => {
    // SyntaxError
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  });
}

Вы также не сможете использовать yield:

function* run() {
  const arr = ;
  arr.forEach(el => {
    // SyntaxError
    yield new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  });
}

Но приведенные выше примеры отлично работают с for/of:

async function asyncFn() {
  const arr = ;
  for (const el of arr) {
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  }
}

function* generatorFn() {
  const arr = ;
  for (const el of arr) {
    yield new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  }
}

Даже если вы пометите свой callback forEach() как async, вам будет сложно заставить асинхронный метод forEach() работать последовательно. Например, приведенный ниже скрипт будет печатать 0-9 в обратном порядке.

async function print(n) {
  // Wait 1 second before printing 0, 0.9 seconds before printing 1, etc.
  await new Promise(resolve => setTimeout(() => resolve(), 1000 - n * 100));
  // Will usually print 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 but order is not strictly
  // guaranteed.
  console.log(n);
}

async function test() {
  .forEach(print);
}

test();

T

Вывод: если вы используете async/await или генераторы, помните, что forEach() является синтаксическим сахаром. Как сахар, его следует использовать экономно и не для всего.

ForEach

Этот цикл, в отличие от предыдущего командлета, не будет работать через конвейер. Если вы попытаетесь использовать этот метод через конвейер, то будет использован командлет.

Это самый простой цикл Powershell, который переходит от одного значения объекта к другому. Синтаксис следующий:

  • $item — хранит текущий элемент из $array. Эту переменную можно вызвать в ScriptBlock;
  • $array — это любая коллекция, из которой нужно получить значения;
  • Scriptblock — это область для написания сценария и остальной логики.

Для примера с foreach в Powershell выполним перебор значений массива:

Так же как и в предыдущем случае каждый новое действие в ScriptBlock должно выполняться с новой строчки:

Выше было написано, что мы не можем использовать конвейер, но исключение такое написание:

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

Использование с командами

Как уже писалось выше не стоит использовать метод Powershell foreach через конвейер. Например так мы можем получить список PSProvider:

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

На примере ниже пример использования цикла и командлета с одни и тем же результатом:

Как видно в случае с командой мы оперируем переменной $PSItem, а с циклом $service, так как мы ее определили еще в начале.

Работа с диапазоном или range

В Powershell можно легко указать диапазон численных значений. Я могу создать массив из чисел с 1 до 10 так:

Так же можно использовать и в итерациях:

Continue и break

Одним из отличий работы с foreach от аналогичной команды является возможность использования contnue и break. 

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

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

Вложенные

Когда у нас есть массив массивов может потребоваться использовать вложенные циклы Powershell. Само их использование не должно вызывать труда, но если вы попробуете использовать операторы break и continue это сработает иначе:

Как вы видите на примере выше у нас остановился только внутренний цикл. Если нужно избежать таких ситуаций используйте OUTER:

Переменные

В этом типе цикла доступны три специальных переменных:

  • $foreach.MoveNext() — переход к следующему элементу;
  • $foreach.current — текущий элемент;
  • $foreach.reset() — обнуляет итерацию. Перебор начнется заново, что приведет к бесконечному циклу.

Такие возможности есть во многих языках программирования, но мне тяжело вспомнить ситуации что бы я их использовал. Для примера ниже мы используем массив чисел с 1 по 10. Самое первое число 1 будет выведено, после чего будет пропущено следующее:

$current просто выведет ту же переменную, объявленную в цикле:

» Referring to Instances

When is set, Terraform distinguishes between the block itself
and the multiple resource or module instances associated with it. Instances are
identified by a map key (or set member) from the value provided to .

  • or (for example, ) refers to the block.
  • or (for example, ,
    , etc.) refers to individual instances.

This is different from resources and modules without or , which can be
referenced without an index or key.

Similarly, resources from child modules with multiple instances are prefixed
with when displayed in plan output and elsewhere in the UI.
For a module without or , the address will not contain
the module index as the module’s name suffices to reference the module.

Note: Within nested or blocks, the special
object refers to the current resource instance, not the resource block
as a whole.

Backward Incompatible Changes

Some rare cases where the foreach statement behavior was undefined may be changed. The implementation changes few such PHPT tests. The list and explanation follows:

  • Zend/tests/bug40509.phpt — foreach be value doesn’t change internal pointer
  • Zend/tests/bug40705.phpt — foreach be value doesn’t change internal pointer
  • tests/lang/bug23624.phpt — foreach be value doesn’t change internal pointer
  • tests/lang/foreachLoop.001.phpt — foreach be value doesn’t change internal pointer
  • tests/lang/foreachLoop.009.phpt — modification of array in foreach by value doesn’t have effect
  • tests/lang/foreachLoop.011.phpt — replacement of array in foreach by value doesn’t have effect
  • tests/lang/foreachLoop.013.phpt — modification of array in foreach by reference through internal functions
  • tests/lang/foreachLoop.014.phpt — modification of array in foreach by value doesn’t have effect
  • tests/lang/foreachLoop.015.phpt — modification of array in foreach by reference through internal functions
  • tests/lang/foreachLoopObjects.006.phpt — replacement of array in foreach by value doesn’t have effect

Shorting Circuits (One-time Loop)

foreach can be used as a code block that runs exactly once, but can be exited from with break or continue (seen in a c.l.t post by Bruce Hartweg):

foreach _ _ {
    # some processing
    if {$somecondition} break
    # some other processing
    if {$someothercondition} break
    # still more processing
}

This is an alternative to nested if structures.

RS is not sure whether to recommend this style.. but proof again that you can do more with Tcl than you’d imagine…;-) Well hell, then add some sugar:

interp alias {} breakable {} foreach _ _
breakable { ;# or 'fragile'?
    # some processing
    if {$somecondition} break
    # some other processing
    if {$someothercondition} break
    # still more processing
}

Or, to make your intention clearer:

interp alias {} make {} foreach
make or break {
    ...
}

AMG: This is like the do {…} while (0); idiom in C, which is useful not only in macros but also for creating a «structured goto» using break. Perhaps unfortunately, continue can’t be used to go back to the top, since it first checks the loop condition; otherwise this idiom would effectively create two line labels at the same time. ;^) Very occasionally I wish for a «redo» statement that restarts the current iteration of the loop, bypassing both the loop condition and for’s increment clause.

Заключение

Как правило, for/of — это самый надежный способ перебора массива в JavaScript. Он более лаконичен, чем обычный цикл for, и не имеет такого количества граничных случаев, как for/in и forEach(). Основным недостатком for/of является то, что вам нужно проделать дополнительную работу для доступа к индексу массива (см. дополнение), и вы не можете строить цепочки кода, как вы можете это делать с помощью forEach(). Но если вы знаете все особенности forEach(), то во многих случаях его использование делает код более лаконичным.

Дополнение: Чтобы получить доступ к текущему индексу массива в цикле for/of, вы можете использовать функцию  .

for (const  of arr.entries()) {
  console.log(i, v); // Prints "0 a", "1 b", "2 c"
}

Оригинал: For vs forEach() vs for/in vs for/of in JavaScript

Spread the love

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *