aboutsummaryrefslogtreecommitdiff
path: root/files/vi/web/javascript/reference/statements/for...of/index.html
blob: 5bd72040eb501bb4b745233b4bf7fa2e574881a1 (plain)
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
---
title: for...of
slug: Web/JavaScript/Reference/Statements/for...of
tags:
  - ECMAScript 2015
  - JavaScript
  - Reference
  - Statement
translation_of: Web/JavaScript/Reference/Statements/for...of
---
<div>{{jsSidebar("Statements")}}</div>

<p>Cú pháp <strong><code>for...of</code></strong> để chạy <a href="/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol">vòng lặp </a> trên {{jsxref("String")}}, {{jsxref("Array")}}, đối tượng tương tự <code>Array</code> (như {{jsxref("Functions/arguments", "arguments")}} hoặc {{domxref("NodeList")}}), {{jsxref("TypedArray")}}, {{jsxref("Map")}}, {{jsxref("Set")}}.</p>

<div>{{EmbedInteractiveExample("pages/js/statement-forof.html")}}</div>

<p class="hidden">Ví dụ được lưu trên GitHub repository. Nếu muốn đóng góp, bạn có thể clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> và gởi lên pull request.</p>

<h2 id="Cú_pháp">Cú pháp</h2>

<pre class="syntaxbox notranslate">for (<em>tên-biến</em> of <em>đối-tượng-chạy-vòng-lặp</em>) {
  <em>...câu lệnh...</em>
}
</pre>

<dl>
 <dt><code>tên biến</code></dt>
 <dd><br>
 Trên mỗi lần lặp, một giá trị của một thuộc tính khác nhau được gán cho biến. biến có thể được khai báo với const, let hoặc var.</dd>
 <dt><code>đối tượng để chạy vòng lặp</code></dt>
 <dd>Đối tượng có các thuộc tính có thể được lặp lại (<em>iterable</em>).</dd>
</dl>

<h2 id="Ví_dụ">Ví dụ</h2>

<h3 id="Lặp_qua_một_jsxrefArray">Lặp qua một {{jsxref("Array")}}</h3>

<pre class="brush:js notranslate">let iterable = [10, 20, 30];

for (let value of iterable ) {
  value += 1;
  console.log(value);
}
// 11
// 21
// 31
</pre>

<p>Có thể khai báo bằng <a href="/en-US/docs/Web/JavaScript/Reference/Statements/const"><code>const</code></a> thay cho <a href="/en-US/docs/Web/JavaScript/Reference/Statements/let"><code>let</code></a>, nếu không có thay đổi biến bên trong vòng lặp.</p>

<pre class="brush:js notranslate">let iterable= [10, 20, 30];

for (const value of iterable) {
  console.log(value);
}
// 10
// 20
// 30
</pre>

<h3 id="Lặp_qua_một_jsxrefString">Lặp qua một {{jsxref("String")}}</h3>

<pre class="brush:js notranslate">const iterable = 'boo';

for (const value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"
</pre>

<h3 id="Lặp_qua_jsxrefTypedArray">Lặp qua {{jsxref("TypedArray")}}</h3>

<pre class="brush:js notranslate">const iterable = new Uint8Array([0x00, 0xff]);

for (const value of iterable) {
  console.log(value);
}
// 0
// 255
</pre>

<h3 id="Lặp_qua_một_jsxrefMap">Lặp qua một {{jsxref("Map")}}</h3>

<pre class="brush:js notranslate">const iterable = new Map([['a', 1], ['b', 2], ['c', 3]]);

for (const entry of iterable) {
  console.log(entry);
}
// ['a', 1]
// ['b', 2]
// ['c', 3]

for (const [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3
</pre>

<h3 id="Loop_qua_một_jsxrefSet">Loop qua một {{jsxref("Set")}}</h3>

<pre class="brush:js notranslate">const iterable = new Set([1, 1, 2, 2, 3, 3]);

for (const value of iterable) {
  console.log(value);
}
// 1
// 2
// 3
</pre>

<h3 id="Lặp_qua_một_đối_tượng_arguments">Lặp qua một đối tượng <code>arguments</code></h3>

<p>Lặp qua đối tượng {{jsxref("Functions/arguments", "arguments")}} để có tất cả giá trị được truyền vào trong hàm:</p>

<pre class="brush: js notranslate">(function() {
  for (const argument of arguments) {
    console.log(argument);
  }
})(1, 2, 3);

// 1
// 2
// 3</pre>

<h3 id="Lặp_qua_một_tập_DOM">Lặp qua một tập DOM</h3>

<p>Lặp qua một tập DOM như {{domxref("NodeList")}}: ví dụ bên dưới, thêm class <code>read</code> cho các đoạn văn bản nào là con trực tiếp của article:</p>

<pre class="brush:js notranslate">// Lưu ý: Chỉ hoạt động động trên các platforms có
// hiện thực NodeList.prototype[Symbol.iterator]
const articleParagraphs = document.querySelectorAll('article &gt; p');

for (const paragraph of articleParagraphs) {
  paragraph.classList.add('read');
}
</pre>

<h3 id="Đóng_vòng_lặp">Đóng vòng lặp</h3>

<p>Trong vòng lặp <code>for...of</code>, có thể ngừng lặp giữa chừng bằng <code>break</code>, <code>continue</code>, <code>throw</code> hoặc <code>return</code>. Trong các trường hợp này, vòng lặp sẽ được ngưng lại.</p>

<pre class="brush: js notranslate">function* foo(){
  yield 1;
  yield 2;
  yield 3;
};

for (const o of foo()) {
  console.log(o);
  break; // đóng vòng lặp, tiếp tục thực thi bên ngoài vòng lặp
}
console.log('Xong')
</pre>

<h3 id="Lặp_qua_generator">Lặp qua generator</h3>

<p>Bạn cũng có thể lặp qua hàm <a href="/en-US/docs/Web/JavaScript/Reference/Statements/function*">generators</a>, ví dụ:</p>

<pre class="brush:js notranslate">function* fibonacci() { // một hàm generator
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (const n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n &gt;= 1000) {
    break;
  }
}
</pre>

<h4 id="Không_tái_sử_dụng_generator">Không tái sử dụng generator</h4>

<p>Không nên re-used Generator, ngay cả khi vòng lặp <code>for...of</code> bị kết thúc sớm bằng {{jsxref("Statements/break", "break")}}. Khi thoát khỏi vòng lặp, generator sẽ kết thúc và cố lặp lại lần nữa sẽ không cho thêm bất kỳ kết quả yield nào khác.</p>

<pre class="brush: js example-bad notranslate">const gen = (function *(){
  yield 1;
  yield 2;
  yield 3;
})();
for (const o of gen) {
  console.log(o);
  break;  // Closes iterator
}

// Không dùng lại generator, đoạn code như thế này không hợp lý!
for (const o of gen) {
  console.log(o); // Không bao giờ được gọi
}
</pre>

<h3 id="Lặp_qua_các_đối_tượng_khác">Lặp qua các đối tượng khác</h3>

<p>Bạn cũng có thể loop qua các đối tượng tự định nghĩa, nếu có hiện thực <a href="/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable">iterable</a>:</p>

<pre class="brush:js notranslate">const iterable = {
  [Symbol.iterator]() {
    return {
      i: 0,
      next() {
        if (this.i &lt; 3) {
          return { value: this.i++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (const value of iterable) {
  console.log(value);
}
// 0
// 1
// 2
</pre>

<h3 id="Sự_khác_biệt_giữa_for...of_và_for...in">Sự khác biệt giữa <code>for...of</code><code>for...in</code></h3>

<p>Cú pháp {{jsxref("Statements/for...in", "for...in")}} lặp qua các đối tượng <a href="/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">được đếm</a>, theo một thứ tự tùy ý.</p>

<p>Cú pháp <code>for...of</code> lặp qua đối tượng dữ liệu <a href="/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterables">có thể lặp</a>.</p>

<p>Ví dụ sau để thấy sự khác nhau giữa <code>for...of</code> và <code>for...in</code> khi sử dụng với {{jsxref("Array")}}.</p>

<pre class="brush:js notranslate">Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};

const iterable = [3, 5, 7];
iterable.foo = 'hello';

for (const i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (const i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}

for (const i of iterable) {
  console.log(i); // logs 3, 5, 7
}
</pre>

<p>Giải thích ví dụ trên</p>

<pre class="brush: js notranslate">Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};

const iterable = [3, 5, 7];
iterable.foo = 'hello';</pre>

<p>Tất cả object sẽ kế thừa thuộc tính <code>objCustom</code> và tất cả {{jsxref("Array")}} sẽ kết thừa thuộc tính <code>arrCustom</code> bởi vì chúng ta thêm nó vào bằng {{jsxref("Object.prototype")}}{{jsxref("Array.prototype")}}. <code>iterable</code> kế thừa cả <code>objCustom</code><code>arrCustom</code>.</p>

<pre class="brush: js notranslate">for (const i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}</pre>

<p>Vòng vòng lặp này chỉ log <a href="/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">thuộc tính được đếm</a> của <code>iterable</code>, theo thứ tự được đưa vào. Nó không log các <strong>element</strong> của array <code>3</code>, <code>5</code>, <code>7</code> hoặc <code>hello</code> bởi vì nó là không thuộc tính được đếm. Nó log giá trị <strong>index</strong> cũng như <code>arrCustom</code><code>objCustom</code>.</p>

<pre class="brush: js notranslate">for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}</pre>

<p>Vòng loop tương tự như ở trên, nhưng sử dụng {{jsxref("Object.prototype.hasOwnProperty()", "hasOwnProperty()")}} để kiểm tra, nếu tìm thấy một property của chính nó chứ không phải kế thừa và log kết quả ra. Các Property <code>0</code>, <code>1</code>, <code>2</code><code>foo</code> được log bởi vì nó không phải được kết thừa.</p>

<pre class="brush: js notranslate">for (const i of iterable) {
  console.log(i); // logs 3, 5, 7
}</pre>

<p>Vòng lặp và log ra giá trị bên trong đối tượng <code>iterable</code> như một <a href="/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterables">iterable object</a><strong> </strong> được khai báo để lặp, chính là các element bên trong mảng <code>3</code>, <code>5</code>, <code>7</code> và không bao gồm các <strong>property</strong> của object.</p>

<h2 id="Đặc_điểm">Đặc điểm</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Đặc điểm</th>
   <th scope="col">Status</th>
   <th scope="col">Ghi chú</th>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-for-in-and-for-of-statements', 'for...of statement')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Initial definition.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-for-in-and-for-of-statements', 'for...of statement')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="Trình_duyệt_hổ_trợ">Trình duyệt hổ trợ</h2>

<div class="hidden">Nếu muốn đóng góp dữ liệu cho bảng này, vui lòng check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> và gởi chúng tôi pull request.</div>

<p>{{Compat("javascript.statements.for_of")}}</p>

<h2 id="Xem_thêm">Xem thêm</h2>

<ul>
 <li>{{jsxref("Array.prototype.forEach()")}}</li>
 <li>{{jsxref("Map.prototype.forEach()")}}</li>
</ul>