1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
|
---
title: Array.prototype.forEach()
slug: Web/JavaScript/Reference/Global_Objects/Array/forEach
tags:
- Array
- ECMAScript5
- JavaScript
- Method
- Prototype
- Reference
- forEach
- polyfill
translation_of: Web/JavaScript/Reference/Global_Objects/Array/forEach
---
<div>{{JSRef("Global_Objects", "Array")}}</div>
<p>Метод <code><strong>forEach()</strong></code> выполняет указанную функцию один раз для каждого элемента в массиве.</p>
<div>{{EmbedInteractiveExample("pages/js/array-foreach.html")}}</div>
<p class="hidden">Источник этого интерактивного примера хранится в GitHub. Если вы хотите внести вклад в проект интерактивных примеров, пожалуйста, клонируйте <a href="https://github.com/mdn/interactive-examples"> https://github.com/mdn/interactive-examples</a> и отправьте нам pull request.</p>
<h2 id="Syntax">Синтаксис</h2>
<pre><var>arr</var>.forEach(function <var>callback(currentValue, index, array) {
//your iterator
}</var>[, <var>thisArg</var>]);</pre>
<h3 id="Parameters">Параметры</h3>
<dl>
<dt><code>callback</code></dt>
<dd>Функция, которая будет вызвана для каждого элемента массива. Она принимает от одного до трёх аргументов:</dd>
<dd>
<dl>
<dt><code>currentValue</code></dt>
<dd>Текущий обрабатываемый элемент в массиве.</dd>
<dt><code>index</code>{{optional_inline}}</dt>
<dd>Индекс текущего обрабатываемого элемента в массиве.</dd>
<dt><code>array</code>{{optional_inline}}</dt>
<dd>Массив, по которому осуществляется проход.</dd>
</dl>
</dd>
<dt><code>thisArg</code></dt>
<dd>Необязательный параметр. Значение, используемое в качестве <code>this</code> при вызове функции <code>callback</code>.</dd>
</dl>
<h3 id="Возвращаемое_значение">Возвращаемое значение</h3>
<p>{{jsxref("undefined")}}.</p>
<h2 id="Description">Описание</h2>
<p>Метод <code>forEach()</code> выполняет функцию <code>callback</code> один раз для каждого элемента, находящегося в массиве в порядке возрастания. Она не будет вызвана для удалённых или пропущенных элементов массива. Однако, она будет вызвана для элементов, которые присутствуют в массиве и имеют значение {{jsxref("Global_Objects/undefined", "undefined")}}.</p>
<p>Функция <code>callback</code> будет вызвана с <strong>тремя аргументами</strong>:</p>
<ul>
<li>значение элемента (<strong>value</strong>)</li>
<li>индекс элемента (<strong>index</strong>)</li>
<li>массив, по которому осуществляется проход (<strong>array</strong>)</li>
</ul>
<p>Если в метод <code>forEach()</code> был передан параметр <code>thisArg</code>, при вызове <code>callback</code> он будет использоваться в качестве значения <code>this</code>. В противном случае, в качестве значения <code>this</code> будет использоваться значение {{jsxref("Global_Objects/undefined", "undefined")}}. В конечном итоге, значение <code>this</code>, наблюдаемое из функции <code>callback</code>, определяется согласно {{jsxref('Operators/this', 'обычным правилам определения <code>this</code>, видимого из функции')}}.</p>
<p>Диапазон элементов, обрабатываемых методом <code>forEach()</code>, устанавливается до первого вызова функции <code>callback</code>. Элементы, добавленные в массив после начала выполнения метода <code>forEach()</code>, не будут посещены функцией <code>callback</code>. Если существующие элементы массива изменятся, значения, переданные в функцию <code>callback</code>, будут значениями на тот момент времени, когда метод <code>forEach()</code> посетит их; удалённые элементы посещены не будут. Если уже посещённые элементы удаляются во время итерации (например, с помощью {{jsxref("Array.prototype.shift()", "shift()")}}), последующие элементы будут пропущены. ({{jsxref('Global_Objects/Array/forEach', 'Смотри пример ниже', 'Модификация_массива_во_время_итерации')}})</p>
<div class="note">
<p><strong>Примечание:</strong> Не существует способа остановить или прервать цикл <code>forEach()</code> кроме как выбрасыванием исключения. Если вам необходимо такое поведение, метод <code>forEach()</code> неправильный выбор.</p>
<p>Досрочное прекращение может быть достигнуто с:</p>
<ul>
<li>Простой цикл {{jsxref('Statements/for', 'for')}}</li>
<li>Циклы {{jsxref('Statements/for...of', 'for...of')}} / {{jsxref('Statements/for...in', 'for...in')}}</li>
<li>{{jsxref("Array.prototype.every()")}}</li>
<li>{{jsxref("Array.prototype.some()")}}</li>
<li>{{jsxref("Array.prototype.find()")}}</li>
<li>{{jsxref("Array.prototype.findIndex()")}}</li>
</ul>
<p>Если нужно протестировать элементы массива на условие и нужно вернуть булево значение, вы можете воспользоваться методами {{jsxref("Array.prototype.every()", "every()")}}, {{jsxref("Array.prototype.some()", "some()")}}, {{jsxref("Array.prototype.find()", "find()")}} или {{jsxref("Array.prototype.findIndex()", "findIndex()")}}.</p>
<p>Метод <code>forEach()</code> выполняет функцию <code>callback</code> один раз для каждого элемента массива; в отличие от методов {{jsxref("Array.prototype.every()", "every()")}} и {{jsxref("Array.prototype.some()", "some()")}}, он всегда возвращает значение {{jsxref("Global_Objects/undefined", "undefined")}}.</p>
</div>
<h2 id="Examples">Примеры</h2>
<h3 id="sparseArray">Нет операции для неинициализированных значений (разреженные массивы)</h3>
<pre class="brush: js">const arraySparse = [1,3,,7]
let numCallbackRuns = 0
arraySparse.forEach((element) => {
console.log(element)
numCallbackRuns++
})
console.log("numCallbackRuns: ", numCallbackRuns)
// 1
// 3
// 7
// numCallbackRuns: 3
// комментарий: как вы видите пропущенное значение между 3 и 7 не вызывало функцию callback.</pre>
<h3 id="Конвертируем_цикл_for_в_forEach">Конвертируем цикл for в forEach</h3>
<pre class="brush:js">const items = ['item1', 'item2', 'item3']
const copy = []
// до
for (let i = 0; i < items.length; i++) {
copy.push(items[i])
}
// после
items.forEach(function(item){
copy.push(item)
})
</pre>
<h3 id="Printing_the_contents_of_an_array">Печать содержимого массива</h3>
<div class="blockIndicator note">
<p><strong>Примечание:</strong> Для отображения содержимого массива в консоли вы можете использовать <a href="/ru/docs/Web/API/Console/table" title="Отображает табличные данные в виде таблицы"><code>console.table()</code></a>, который выводит отформатированную версию массива.</p>
<p>Следующий пример иллюстрирует альтернативный подход, использующий <code>forEach()</code>.</p>
</div>
<p>Следующий код выводит каждый элемент массива на новой строке журнала:</p>
<pre class="brush: js">function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// Обратите внимание на пропуск по индексу 2, там нет элемента, поэтому он не посещается
[2, 5, , 9].forEach(logArrayElements);
// логи:
// a[0] = 2
// a[1] = 5
// a[3] = 9
</pre>
<h3 id="Использование_thisArg">Использование <code><var>thisArg</var></code></h3>
<p>Следующий (надуманный) пример обновляет свойства объекта, когда перебирает записи массива:</p>
<pre class="brush:js">function Counter() {
this.sum = 0
this.count = 0
}
Counter.prototype.add = function(array) {
array.forEach((entry) => {
this.sum += entry
++this.count
}, this)
// ^---- Note
}
const obj = new Counter()
obj.add([2, 5, 9])
obj.count
// 3
obj.sum
// 16
</pre>
<p>Поскольку в <code>forEach()</code>передан параметр <code><var>thisArg</var></code> (<code>this</code>), он затем передаётся в <code><var>callback</var></code> при каждом вызове. И callback использует его в качестве собственного значения <code>this</code>.</p>
<div class="note">
<p><strong>Примечание:</strong> Если при передаче callback функции используется {{jsxref('Functions/Arrow_functions', 'выражение стрелочной функции')}}, параметр <code><var>thisArg</var></code> может быть опущен, так как все стрелочные функции лексически привязываются к значению{{jsxref("Operators/this", "this")}}.</p>
</div>
<h3 id="Breaking_a_loop">Прерывание цикла</h3>
<p>Следующий код использует {{jsxref("Array.prototype.every()")}} для логирования содержимого массива и останавливается при превышении значением заданного порогового значения <code>THRESHOLD</code>.</p>
<pre class="brush: js">var THRESHOLD = 12;
var v = [5, 2, 16, 4, 3, 18, 20];
var res;
res = v.every(function(element, index, array) {
console.log('element:', element);
if (element >= THRESHOLD) {
return false;
}
return true;
});
console.log('res:', res);
// логи:
// element: 5
// element: 2
// element: 16
// res: false
res = v.some(function(element, index, array) {
console.log('element:', element);
if (element >= THRESHOLD) {
return true;
}
return false;
});
console.log('res:', res);
// логи:
// element: 5
// element: 2
// element: 16
// res: true
</pre>
<h3 id="An_object_copy_function">Функция копирования объекта</h3>
<p>Следующий код создаёт копию переданного объекта. Существует несколько способов создания копии объекта, и это один из них. Он позволяет понять, каким образом работает <code>Array.prototype.forEach()</code>, используя функции мета-свойств <code>Object.*</code> из ECMAScript 5.</p>
<pre class="brush: js">function copy(o) {
var copy = Object.create(Object.getPrototypeOf(o));
var propNames = Object.getOwnPropertyNames(o);
propNames.forEach(function(name) {
var desc = Object.getOwnPropertyDescriptor(o, name);
Object.defineProperty(copy, name, desc);
});
return copy;
}
var o1 = { a: 1, b: 2 };
var o2 = copy(o1); // теперь o2 выглядит также, как и o1
</pre>
<h3 id="Модификация_массива_во_время_итерации">Модификация массива во время итерации</h3>
<p>В следующем примере в лог выводится <code>"one"</code>, <code>"two"</code>, <code>"four"</code>.</p>
<p>При достижении записи, содержащей значение <code>'two'</code>, первая запись всего массива удаляется, в результате чего все оставшиеся записи перемещаются на одну позицию вверх. Поскольку элемент <code>'four'</code> теперь находится на более ранней позиции в массиве, <code>'three'</code> будет пропущен.</p>
<p><code>forEach()</code> не делает копию массива перед итерацией.</p>
<pre class="brush:js">let words = ['one', 'two', 'three', 'four']
words.forEach((word) => {
console.log(word)
if (word === 'two') {
words.shift()
}
})
// one
// two
// four
</pre>
<h3 id="Выравнивание_уплощение_массива">Выравнивание (уплощение) массива</h3>
<p>Следующий пример приведён только для целей обучения. Если вы хотите выравнять массив с помощью встроенных методов, вы можете использовать {{jsxref("Array.prototype.flat()")}}</p>
<pre class="brush: js">function flatten(arr) {
const result = []
arr.forEach((i) => {
if (Array.isArray(i)) {
result.push(...flatten(i))
} else {
result.push(i)
}
})
return result
}
// Usage
const nested = [1, 2, 3, [4, 5, [6, 7], 8, 9]]
flatten(nested) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
</pre>
<h2 id="Polyfill">Полифил</h2>
<p>Метод <code>forEach()</code> был добавлен к стандарту ECMA-262 в 5-м издании; поэтому он может отсутствовать в других реализациях стандарта. Вы можете работать с ним, добавив следующий код в начало ваших скриптов, он позволяет использовать <code>forEach()</code> в реализациях, которые не поддерживают этот метод. Этот алгоритм является точно тем, что описан в ECMA-262 5-го издания; он предполагает, что {{jsxref("Object")}} и {{jsxref("TypeError")}} имеют свои первоначальные значения и что <code>callback.call</code> вычисляется в оригинальное значение {{jsxref("Function.prototype.call()")}}.</p>
<pre class="brush: js">// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.18
// Ссылка (en): http://es5.github.io/#x15.4.4.18
// Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.18
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Положим O равным результату вызова ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length".
// 3. Положим len равным ToUint32(lenValue).
var len = O.length >>> 0;
// 4. Если IsCallable(callback) равен false, выкинем исключение TypeError.
// Смотрите: http://es5.github.com/#x9.11
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Положим k равным 0
k = 0;
// 7. Пока k < len, будем повторять
while (k < len) {
var kValue;
// a. Положим Pk равным ToString(k).
// Это неявное преобразование для левостороннего операнда в операторе in
// b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk.
// Этот шаг может быть объединён с шагом c
// c. Если kPresent равен true, то
if (k in O) {
// i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk.
kValue = O[k];
// ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и
// списком аргументов, содержащим kValue, k и O.
callback.call(T, kValue, k, O);
}
// d. Увеличим k на 1.
k++;
}
// 8. Вернём undefined.
};
}
</pre>
<h2 id="Specifications">Спецификации</h2>
{{Specifications}}
<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
<div>
<p>{{Compat}}</p>
</div>
<h2 id="See_also">Смотрите также</h2>
<ul>
<li>{{jsxref("Array.prototype.find()")}}</li>
<li>{{jsxref("Array.prototype.findIndex()")}}</li>
<li>{{jsxref("Array.prototype.map()")}}</li>
<li>{{jsxref("Array.prototype.every()")}}</li>
<li>{{jsxref("Array.prototype.some()")}}</li>
<li>{{jsxref("Map.prototype.forEach()")}}</li>
<li>{{jsxref("Set.prototype.forEach()")}}</li>
</ul>
|