tek4

Map và WeakMap trong JavaScript

by - September. 26, 2021
Kiến thức
Học
<p><img class="aligncenter wp-image-8193 size-full" src="https://tek4.vn/wp-content/uploads/2021/02/Capture-49.png" alt="Map v&agrave; WeakMap trong JavaScript" width="560" height="342" /></p> <p>Trong b&agrave;i viết n&agrave;y, ta sẽ t&igrave;m hiểu về kiểu dữ liệu Map v&agrave; WeakMap 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>Kiểu dữ liệu cấu tr&uacute;c Map trong JavaScript</h1> <p>JavaScript ES6 đ&atilde; đưa ra hai kiểu cấu tr&uacute;c dữ liệu mới, bao gồm kiểu dữ liệu Map v&agrave; WeakMap.</p> <p>Kiểu dữ liệu cấu tr&uacute;c Map hoạt động tương tự như c&aacute;c đối tượng trong JavaScript, cho ph&eacute;p ch&uacute;ng ta lưu trữ c&aacute;c phần tử trong một cặp kh&oacute;a v&agrave; gi&aacute; trị.</p> <p>C&aacute;c phần tử trong cấu tr&uacute;c Map được th&ecirc;m v&agrave;o theo thứ tự được ch&egrave;n. Tuy nhi&ecirc;n, kh&ocirc;ng giống với đối tượng, Map c&oacute; thể chứa c&aacute;c đối tượng, h&agrave;m v&agrave; c&aacute;c kiểu dữ liệu kh&aacute;c l&agrave;m kh&oacute;a.</p> <h2>Tạo Map trong JavaScript</h2> <p>Để tạo một kiểu dữ liệu cấu tr&uacute;c Map, ch&uacute;ng ta sẽ sử dụng h&agrave;m tạo <code class="EnlighterJSRAW" data-enlighter-language="generic">Map()</code>.</p> <p>V&iacute; dụ: Tạo một đối tượng c&oacute; kiểu dữ liệu Map.</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const a = new Map();</pre> <h2>Ch&egrave;n phần tử v&agrave;o trong đối tượng c&oacute; kiểu dữ liệu cấu tr&uacute;c Map</h2> <p>Sau khi tạo một biến c&oacute; kiểu dữ liệu cấu tr&uacute;c Map, ta c&oacute; thể sử dụng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">set()</code>để ch&egrave;n c&aacute;c phần tử.</p> <p>V&iacute; dụ: Ch&egrave;n phần tử v&agrave;o đối tượng Map.</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('StudentList',{ten: 'Nam', ID: 190}); console.log(sinh_vien);</pre> <p>Kết quả:</p> <pre>Map{'StudentList' =&gt; {ten: 'Nam', ID: 190}}</pre> <p>Ta cũng c&oacute; thể sử dụng c&aacute;c đối tượng hoặc h&agrave;m l&agrave;m kh&oacute;a.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); let a = {}; sinh_vien.set(a, {ten: 'Nam', ID: 100}); console.log(sinh_vien);</pre> <p>Kết quả:</p> <pre>Map{{} =&gt; {ten: 'Nam', ID: 100}}</pre> <h2>Truy cập v&agrave;o c&aacute;c phần tử c&oacute; trong đối tượng của kiểu dữ liệu Map</h2> <p>Ta c&oacute; thể truy cập v&agrave;o c&aacute;c phần tử trong đối tượng của kiểu dữ liệu cấu tr&uacute;c Map bằng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">get()</code>.</p> <p>V&iacute; dụ: Truy cập v&agrave;o c&aacute;c phần tử của đối tượng Map.</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('StudentList', {Ten: 'Nam', ID: 100}); console.log(sinh_vien.get('StudentList'));</pre> <p>Kết quả:</p> <pre>{Ten: 'Nam', ID: 100}</pre> <h2>Kiểm tra c&aacute;c phần tử c&oacute; trong đối tượng Map</h2> <p>Ta c&oacute; thể sử dụng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">has()</code>để kiểm tra xem phần tử c&oacute; trong đối tượng kiểu dữ liệu Map hay kh&ocirc;ng.</p> <p>V&iacute; dụ: Kiểm tra phần tử c&oacute; trong đối tượng Map.</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('StudentList', {Ten: 'Nam', ID: 100}); console.log(sinh_vien.has('StudentList'));</pre> <p>Kết quả:</p> <pre>True</pre> <h2>Loại bỏ c&aacute;c phần tử khỏi đối tượng Map</h2> <p>Ta c&oacute; thể sử dụng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">clear()</code>v&agrave; <code class="EnlighterJSRAW" data-enlighter-language="generic">delete()</code>để x&oacute;a c&aacute;c phần tử khỏi đối tượng c&oacute; kiểu dữ liệu cấu tr&uacute;c Map. Phương thức delete() trả về true nếu một cặp kh&oacute;a v&agrave; gi&aacute; trị được x&aacute;c định c&oacute; tồn tại v&agrave; đ&atilde; bị x&oacute;a, hoặc nếu kh&ocirc;ng sẽ trả về false.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('StudentList', {Ten: 'Nam', ID: 100}); sinh_vien.delete('a'); console.log(sinh_vien); sinh_vien.delete('StudentList'); console.log(sinh_vien);</pre> <p>Kết quả:</p> <pre>Map{'StudentList' =&gt; {Ten: 'Nam', ID: 100}} Map{}</pre> <p>Phương thức clear() sẽ loại bỏ tất cả c&aacute;c cặp kh&oacute;a v&agrave; gi&aacute; trị khỏi một đối tượng Map.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('StudentList', {Ten: 'Nam', ID: 100}); sinh_vien.clear(); console.log(sinh_vien);</pre> <p>Kết quả:</p> <pre>Map {}</pre> <h2>X&aacute;c định k&iacute;ch thước của đối tượng Map</h2> <p>Ta c&oacute; thể lấy số lượng phần tử trong Map bằng thuộc t&iacute;nh size.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('StudentList', {Ten: 'Nam', ID: 100}); console.log(sinh_vien.size);</pre> <p>Kết quả:</p> <pre>1</pre> <h2>Duyệt qua c&aacute;c phần tử c&oacute; trong đối tượng Map</h2> <p>Ta c&oacute; thể lặp qua c&aacute;c phần tử trong cấu tr&uacute;c Map bằng c&aacute;ch sử dụng v&ograve;ng lặp <code class="EnlighterJSRAW" data-enlighter-language="generic">for...of</code>hoặc phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">forEach()</code>. C&aacute;c phần tử được truy cập theo thứ tự được ch&egrave;n.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('Nam', 100); sinh_vien.set('Thanh', 30); for (let [key, val] of sinh_vien) { &nbsp;&nbsp;&nbsp; console.log(key + ': ' + val); }</pre> <p>Kết quả:</p> <pre>Nam: 100 Thanh: 30</pre> <p>Ta cũng c&oacute; thể nhận được kết quả tương tự như chương tr&igrave;nh tr&ecirc;n bằng phương thức forEach().</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('Nam', 100); sinh_vien.set('Thanh', 30); sinh_vien.forEach(function(val, key) { &nbsp; console.log(key + ': ' + val) })</pre> <p>Kết quả:</p> <pre>Nam: 100 Thanh: 30</pre> <h2>Duyệt qua c&aacute;c kh&oacute;a c&oacute; trong đối tượng Map</h2> <p>Ta c&oacute; thể duyệt qua c&aacute;c th&agrave;nh phần c&oacute; trong đối tượng Map v&agrave; lấy kh&oacute;a bằng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">key()</code>.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('Nam', 100); sinh_vien.set('Thanh', 30); for (let key of sinh_vien.keys()) { &nbsp; console.log(key) }</pre> <p>Kết quả:</p> <pre>Nam Thanh</pre> <h2>Duyệt qua c&aacute;c gi&aacute; trị c&oacute; trong đối tượng Map</h2> <p>Ta c&oacute; thể duyệt qua c&aacute;c gi&aacute; trị c&oacute; trong đối tượng Map v&agrave; lấy c&aacute;c gi&aacute; trị bằng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">values()</code>.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('Nam', 100); sinh_vien.set('Thanh', 30); for (let val of sinh_vien.values()) { &nbsp;&nbsp;&nbsp; console.log(val); }</pre> <p>Kết quả:</p> <pre>100 30</pre> <h2>Lấy ra c&aacute;c cặp kh&oacute;a v&agrave; gi&aacute; trị c&oacute; trong đối tượng Map</h2> <p>Ta c&oacute; thể duyệt qua c&aacute;c th&agrave;nh phần c&oacute; trong đối tượng Map v&agrave; lấy kh&oacute;a v&agrave; gi&aacute; trị của Map bằng phương thức <code class="EnlighterJSRAW" data-enlighter-language="generic">entries()</code>.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">let sinh_vien = new Map(); sinh_vien.set('Nam', 100); sinh_vien.set('Thanh', 30); for (let a of sinh_vien.entries()) { &nbsp;&nbsp;&nbsp; console.log(`${a[0]}: ${a[1]}`); }</pre> <p>Kết quả:</p> <pre>Nam: 100 Thanh: 30</pre> <h2>So s&aacute;nh đối tượng Map với đối tượng trong JavaScript</h2> <table> <tbody> <tr> <td style="text-align: center;">Đối tượng kiểu dữ liệu Map</td> <td style="text-align: center;">Đối tượng kiểu dữ liệu Object</td> </tr> <tr> <td>Chứa c&aacute;c đối tượng v&agrave; c&aacute;c kiểu dữ liệu kh&aacute;c c&oacute; thể đặt l&agrave;m kh&oacute;a.</td> <td>Chỉ chứa c&aacute;c chuỗi k&yacute; tự v&agrave; kiểu Symbol đặt l&agrave;m kh&oacute;a.</td> </tr> <tr> <td>C&oacute; thể được duyệt qua trực tiếp v&agrave; truy cập v&agrave;o c&aacute;c gi&aacute; trị.</td> <td>Chỉ c&oacute; thể được duyệt qua bằng c&aacute;ch truy cập v&agrave;o c&aacute;c kh&oacute;a.</td> </tr> <tr> <td>Số lượng phần tử được t&iacute;nh sẵn bởi thuộc t&iacute;nh size.</td> <td>Số lượng phần tử được t&iacute;nh bằng tay.</td> </tr> <tr> <td>Ph&ugrave; hợp cho c&aacute;c chương tr&igrave;nh đ&ograve;i hỏi việc th&ecirc;m hoặc x&oacute;a c&aacute;c phần tử thường xuy&ecirc;n.</td> <td>Kh&ocirc;ng ph&ugrave; hợp cho c&aacute;c chương tr&igrave;nh đ&ograve;i hỏi việc th&ecirc;m hoặc x&oacute;a c&aacute;c phần tử thường xuy&ecirc;n.</td> </tr> </tbody> </table> <h2>Kiểu dữ liệu WeakMap trong JavaScript</h2> <p>Kiểu dữ liệu WeakMap tương tự như kiểu dữ liệu Map. Tuy nhi&ecirc;n, đối tượng kiểu dữ liệu WeakMap chỉ c&oacute; thể chứa c&aacute;c đối tượng dưới dạng kh&oacute;a.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const sinh_vien = new WeakMap(); console.log(sinh_vien); let a = {}; sinh_vien.set(a, 'Nam'); console.log(sinh_vien);</pre> <p>Kết quả:</p> <pre>WeakMap{&lt;items unknown&gt;} WeakMap{&lt;items unknown&gt;}</pre> <p>Khi ta cố gắng th&ecirc;m c&aacute;c kiểu dữ liệu kh&aacute;c ngo&agrave;i kiểu dữ liệu đối tượng, tr&igrave;nh bi&ecirc;n dịch sẽ đưa ra th&ocirc;ng b&aacute;o lỗi.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const sinh_vien = new WeakMap(); console.log(sinh_vien); let a = {}; sinh_vien.set(a, 'Nam'); weakMap.set('ID', 'Thanh');</pre> <h2>C&aacute;c phương thức của kiểu dữ liệu WeakMap</h2> <p>Kiểu dữ liệu WeakMaps bao gồm c&aacute;c phương thức get(), set(), delete() v&agrave; has(). C&aacute;c phương thức n&agrave;y được sử dụng để l&agrave;m việc với c&aacute;c đối tượng c&oacute; kiểu dữ liệu WeakMap.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const sinh_vien = new WeakMap(); let a = {}; sinh_vien.set(a, 'Nam'); console.log(sinh_vien); console.log(sinh_vien.get(a)); console.log(sinh_vien.has(a)); console.log(sinh_vien.delete(a)); console.log(sinh_vien);</pre> <p>Kết quả:</p> <pre>WeakMap{&lt;items unknown&gt;} Nam true true WeakMap{&lt;items unknown&gt;}</pre> <p><strong><span style="background-color: #ffff00;">Ch&uacute; &yacute;: Kh&ocirc;ng thể duyệt qua c&aacute;c phần tử trong đối tượng c&oacute; kiểu dữ liệu WeakMap.</span></strong></p> <p>Kh&ocirc;ng giống như c&aacute;c đối tượng kiểu Map, c&aacute;c đối tượng c&oacute; kiểu dữ liệu WeakMap kh&ocirc;ng thể được duyệt c&aacute;c th&agrave;nh phần b&ecirc;n trong n&oacute;.</p> <p>V&iacute; dụ:</p> <pre class="EnlighterJSRAW" data-enlighter-language="js">const sinh_vien = new WeakMap(); let a = {}; sinh_vien.set(a, 'Nam'); for (let ket of sinh_vien) { &nbsp;&nbsp;&nbsp; console.log(key); }</pre> <p>Kết quả nhận được sẽ l&agrave; một th&ocirc;ng b&aacute;o lỗi như sau.</p> <pre>TypeError: sinh_vien is not iterable</pre> <p><strong><span style="background-color: #ffff00;">Ch&uacute; &yacute;: Kiểu dữ liệu Map v&agrave; WeakMap trong JavaScript đ&atilde; được giới thiệu trong ES6. Một số tr&igrave;nh duyệt c&oacute; thể sẽ kh&ocirc;ng hỗ trợ việc sử dụng c&aacute;c cấu tr&uacute;c dữ liệu n&agrave;y.</span></strong></p> <p>Tr&ecirc;n đ&acirc;y l&agrave; kh&aacute;i niệm v&agrave; v&iacute; dụ cơ bản về kiểu dữ liệu Map v&agrave; WeakMap 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>