tek4

Iterator và Iterable trong JavaScript

by - September. 26, 2021
Kiến thức
Học
<p><img class="aligncenter wp-image-8256 size-full" src="https://tek4.vn/wp-content/uploads/2021/02/Capture-69.png" alt="Iterator v&agrave; Iterable trong JavaScript" width="753" height="444" /></p> <p>Trong b&agrave;i viết n&agrave;y, ta sẽ c&ugrave;ng t&igrave;m hiểu về Iterator v&agrave; Iterable trong JavaScript c&ugrave;ng với sự trợ gi&uacute;p của c&aacute;c v&iacute; dụ dẫn chứng.</p> <h1>Iterator v&agrave; Iterable trong JavaScript</h1> <p>JavaScript cung cấp một giao thức để duyệt qua c&aacute;c cấu tr&uacute;c dữ liệu. Giao thức n&agrave;y x&aacute;c định c&aacute;ch c&aacute;c cấu tr&uacute;c dữ liệu n&agrave;y được duyệt qua bằng c&aacute;ch sử dụng v&ograve;ng lặp <code class="EnlighterJSRAW" data-enlighter-language="generic">for...of</code>.</p> <p>Giao thức c&oacute; thể được chia th&agrave;nh như sau:</p> <ul> <li>Iterator.</li> <li>Iterable.</li> </ul> <p>Giao thức Iterable đề cập đến một giao thức Iterable phải c&oacute; kh&oacute;a <code class="EnlighterJSRAW" data-enlighter-language="generic">Symbol.iterator</code>.</p> <h2>Iterable trong JavaScript</h2> <p>C&aacute;c cấu tr&uacute;c dữ liệu c&oacute; phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">Symbol.iterator()</code>được gọi l&agrave; c&aacute;c Iterable. V&iacute; dụ: Mảng, Chuỗi k&yacute; tự, Set,...</p> <h2>C&aacute;c giao thức Iterator trong JavaScript</h2> <p>Một Iterator l&agrave; một đối tượng được trả về bởi phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">Symbol.iterator()</code>.</p> <p>Iterator cung cấp phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">next()</code>để truy cập từng phần tử của cấu tr&uacute;c dữ liệu c&oacute; thể lặp tại một thời điểm.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const a = [100, 150 , 230]; const iterator = a[Symbol.iterator](); console.log(iterator); const b = 'Lập tr&igrave;nh JavaScript'; const iterator2 = b[Symbol.iterator](); console.log(iterator2);</pre> <p>Ở đ&acirc;y, việc gọi phương thức Symbol.iterator() cho cả mảng v&agrave; chuỗi sẽ trả về c&aacute;c đối tượng Iterator tương ứng của ch&uacute;ng.</p> <h2>Duyệt qua c&aacute;c đối tượng Iterable</h2> <p>Ta c&oacute; thể sử dụng v&ograve;ng lặp <code class="EnlighterJSRAW" data-enlighter-language="generic">for&hellip;of</code>để duyệt qua c&aacute;c đối tượng Iterable.</p> <p>Ta c&oacute; thể thực hiện việc lặp th&ocirc;ng qua phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">Symbol.iterator()</code>như sau.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const a = [100, 150, 160, 200, 250]; for (let i of&nbsp; a[Symbol.iterator]()) { &nbsp;&nbsp;&nbsp; console.log(i); }</pre> <p>Kết quả:</p> <pre>100 150 160 200 250</pre> <p>Hoặc ta c&oacute; thể chỉ cần lặp qua một mảng như sau.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const a = [150, 160, 170, 190, 250, 270]; for (let i of&nbsp; a) { &nbsp;&nbsp;&nbsp; console.log(i); }</pre> <p>Kết quả:</p> <pre>150 160 170 190 250 270</pre> <p>Ở đ&acirc;y, đối tượng Iterator cho ph&eacute;p v&ograve;ng lặp <code class="EnlighterJSRAW" data-enlighter-language="generic">for...of</code>lặp qua một mảng v&agrave; trả về từng gi&aacute; trị.</p> <h2>Phương thức next()</h2> <p>Đối tượng Iterator c&oacute; một phương thức next() trả về phần tử tiếp theo trong chuỗi. Phương thức next() chứa hai thuộc t&iacute;nh: <code class="EnlighterJSRAW" data-enlighter-language="generic">value</code>v&agrave; <code class="EnlighterJSRAW" data-enlighter-language="generic">done</code>.</p> <ul> <li>Thuộc t&iacute;nh value c&oacute; thể thuộc bất kỳ kiểu dữ liệu n&agrave;o v&agrave; đại diện cho gi&aacute; trị hiện tại trong chuỗi.</li> <li>Thuộc t&iacute;nh done l&agrave; một gi&aacute; trị kiểu dữ liệu boolean cho biết qu&aacute; tr&igrave;nh lặp c&oacute; ho&agrave;n th&agrave;nh hay kh&ocirc;ng. Nếu qu&aacute; tr&igrave;nh lặp chưa ho&agrave;n th&agrave;nh, thuộc t&iacute;nh done được đặt gi&aacute; trị false, nếu kh&ocirc;ng, thuộc t&iacute;nh được đặt th&agrave;nh true.</li> </ul> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const a = ['J', 'a', 'v', 'a', 's','c','r','i','p', 't']; let iterator = a[Symbol.iterator](); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next());</pre> <p>Kết quả:</p> <pre>{value: 'J', done: false} {value: 'a', done: false} {value: 'v', done: false} {value: 'a', done: false} {value: 's', done: false} {value: 'c', done: false} {value: 'r', done: false} {value: 'i', done: false} {value: 'p', done: false} {value: 't', done: false}</pre> <p>Ta c&oacute; thể gọi phương thức next() nhiều lần để lặp qua một đối tượng <code class="EnlighterJSRAW" data-enlighter-language="generic">arrIterator</code>.</p> <ul> <li>Phương thức next() trả về một đối tượng c&oacute; hai thuộc t&iacute;nh: <code class="EnlighterJSRAW" data-enlighter-language="generic">value</code>v&agrave; <code class="EnlighterJSRAW" data-enlighter-language="generic">done</code>.</li> <li>Khi phương thức next() đạt đến phần cuối của d&atilde;y, thuộc t&iacute;nh done được đặt th&agrave;nh gi&aacute; trị false.</li> </ul> <p>V&iacute; dụ 2:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const a = ['J', 'a', 'v', 'a', 's','c','r','i','p', 't']; for (let i of a) { &nbsp;&nbsp;&nbsp; console.log(i); }</pre> <p>Kết quả:</p> <pre>J a v a s c r i p t</pre> <p>V&ograve;ng lặp for&hellip;of thực hiện ho&agrave;n to&agrave;n giống như chương tr&igrave;nh tr&ecirc;n. V&ograve;ng lặp for...of tiếp tục gọi phương thức next() tr&ecirc;n đối tượng Iterator. Sau khi thuộc t&iacute;nh done c&oacute; gi&aacute; trị l&agrave; true, v&ograve;ng lặp for...of sẽ kết th&uacute;c.</p> <h2>Đối tượng Iterator do người d&ugrave;ng tự định nghĩa</h2> <p>Ta cũng c&oacute; thể tạo đối tượng Iterator của ri&ecirc;ng m&igrave;nh v&agrave; gọi phương thức next() để truy cập c&aacute;c phần tử tiếp theo.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">function vi_du(a) { &nbsp;&nbsp;&nbsp; let n = 0; &nbsp;&nbsp;&nbsp; return { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next() { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(n &lt; a.length) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value: a[n++], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; done: false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value: undefined, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; done: true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp; } } let a = ['J', 'a', 'v', 'a', 's','c','r','i','p', 't']; let iterator = vi_du(a); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next());</pre> <p>Kết quả:</p> <pre>{value: 'J', done: false} {value: 'a', done: false} {value: 'v', done: false} {value: 'a', done: false}</pre> <p>Trong chương tr&igrave;nh tr&ecirc;n, ch&uacute;ng ta đ&atilde; tạo đối tượng Iterator của ri&ecirc;ng m&igrave;nh. H&agrave;m vi_du() trả về thuộc t&iacute;nh value v&agrave; thuộc t&iacute;nh done. Mỗi lần phương thức next() được gọi, h&agrave;m vi_du() được thực thi một lần v&agrave; hiển thị gi&aacute; trị của một mảng. Cuối c&ugrave;ng, khi tất cả c&aacute;c phần tử của một mảng đ&atilde; hết, thuộc t&iacute;nh done được đặt th&agrave;nh true, với gi&aacute; trị l&agrave; undefined.</p> <p>Tr&ecirc;n đ&acirc;y l&agrave; kh&aacute;i niệm v&agrave; v&iacute; dụ cơ bản về Iterator v&agrave; Iterable trong JavaScript. Hy vọng mọi người c&oacute; thể &aacute;p dụng v&agrave;o trong chương tr&igrave;nh của m&igrave;nh. Mọi người h&atilde;y tiếp tục theo d&otilde;i c&aacute;c b&agrave;i tiếp theo v&agrave; cập nhật c&aacute;c b&agrave;i tiếp theo về lập tr&igrave;nh JavaScript tr&ecirc;n <a href="http://tek4.vn">tek4</a> nh&eacute;!</p> <p>P/s: Cảm ơn mọi người đ&atilde; tin tưởng tek4!</p>