Javascript sự khác biệt map và weakmap. What make a different?

4648

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Sự khác biệt map và weakmap luôn là một phần kiến thức cần nắm vững đối với lập trình viên Javascript. Nắm rõ sự khác biệt còn phải hiểu lúc nào nên sử dụng loại nào nữa. Đấy, vô vàn vấn đề cần tìm hiểu.

Tuy nhiên, khó cũng phải hiểu. Vì Data Structure không phải muốn dùng sao cũng được. Ở các System lớn, chỉ cần thay đổi một kiểu của DS thôi cũng gây ra hàng tá vấn đề.

Dữ liệu lớn, request xử lý hàng đống. Memory là thứ cần kiểm soát chặt chẽ để đảm bảo hệ thống luôn vận hành trơn tru. Kieblog hân hạnh giới thiệu bài viết sự khác biệt map và weakmap. Bắt đầu ngay thôi nào!

Tuyển dụng Javascript cho bạn

1. Định nghĩa

Map thì đã quá quen thuộc rồi

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

Đối tượng Map lưu cặp key-value (khoá – giá trị) theo thứ tự chèn vào của khoá. Bất kỳ giá trị nào (cả đối tượng (objects) và primitive values) đều có thể sử dụng làm key hoặc value.

WeakMap thì bản thân bao gồm 2 chữ. Weak và Map, hẳn là phải có cái gì đó “yếu hơn” rồi.

The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced. The keys must be objects and the values can be arbitrary values.

Đối tượng WeakMap là collection của các cặp key/value với các key được tham chiếu yếu ớt. Các key phải là đối tượng và các value có thể là bất kỳ giá trị nào. 

Cả Map và WeakMap đều cho phép lưu trữ theo kiểu key-value. Key và uniques và một loạt Value đi kèm. Tuy nhiên vẫn tồn tại một số sự khác biệt map và weakmap.

Javascript sự khác biệt map và weakmap. What make a different
Weak không có nghĩa là yếu. Chỉ “lỏng lẻo” hơn một vài điểm thôi

2. Sự khác biệt Map và Weak Map

2.1 Key Store

Cùng là cơ chế lưu trữ key-value. Nhưng có sự khác biệt rõ ràng về tiêu chuẩn của key.

WeakMap accepts only objects as keys whereas a Map,in addition to objects, accepts primitive datatype such as strings, numbers etc.

WeakMap chỉ chấp nhận kiểu objects đóng vai trò như là key. Trong khi Map, ngoài kiểu Objects, nó còn chấp nhận cả các kiểu nguyên thủy như Strings, Numbers,…

JavaScript
map.set(44, 12);

// Lỗi
weakmap.set(44, 13);

// Lỗi. Không thể tạo WeakMap từ 2D array.
var map_1 = new WeakMap([[1, 2], [4, 5]]);

Mà cái thằng WeakMap này cũng dị. Mấy function hay methods dùng được với map thì không dùng được với Weakmap.

JavaScript
console.log(weakmap.size); //undefined


//loop through the keys in an map
for(var i of map)
{
console.log(i);
}

//loop through the keys in an weakmap doesn't work
for(var i of weakmap)
{
console.log(i);
}

//delete all keys
map.clear();

weakmap.clear(); //but this works

Ngoài chuyện Primitive Type thì còn một vấn đề khác nữa là Memory Leak. Cái này là “cốt lõi”. Có nó mới có chữ Weak trong WeakMap. Khác biệt cốt lõi nhất!

  15 ví dụ sử dụng map, reduce và filter
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

2.2 Vấn đề Memory Leak

Memory thì từ xưa đến nay đã luôn là vấn đề cố hữu của Map. Một Map được tạo ra cũng đồng nghĩa với một phần memory được cấp phát. Cấp thì dễ, nhưng đôi khi mấy anh dev lại quên lấy lại phần đó (mặc dù đã sử dụng xong Map).

Sự khác biệt giữa Map và WeakMap lại là vấn đề này. Đây cũng là điểm khác biệt cần nắm rõ để có lựa chọn sáng suốt khi lựa chọn Map hay WeakMap.

Để dễ hiểu hơn thì ta có thể xem xét ví dụ sau:

JavaScript

var map = new Map();
var weakmap = new WeakMap();

(function(){
var a = {x: 12};
var b = {y: 12};

map.set(a, 1);
weakmap.set(b, 2);
})()

Xét như ví dụ phía trên, function tóm gọn lại từ dòng 4 đến dòng 10. Tuy nhiên để access được b = {y: 12}; bên ngoài function scope thực sự là không thể.

Mặc dù cả Map và Weakmap đều là global access variable. Tuy nhiên cơ chế của WeakMap cho phép Garbage collector xóa pointer tới b của chính nó. Bản thân chữa weak mang nghĩa là yếu, liên kết của weak map tới chính đứa con mà nó set vào là liên kết lỏng lẻo.

So “Map” can cause more garbages in memory. We can say that “Map” references are strong pointer whereas “WeakMap” references are weak pointers.

Chính vì vậy Map có thể chiếm dụng khá nhiều về mặt memory. Cũng có thể nói “map” tham chiếu mạnh hơn so với “WeakMap”. Tham chiếu ở đây được hiểu là tham chiếu tới memory được cấp phát.

3. Lúc nào nên xài cái gì?

Không phải ngẫu nhiên mà Javascript ES6 bổ sung thêm WeakMap. Rõ ràng Map luôn có sự bất tiện khi sử dụng.

Javascript sự khác biệt map và weakmap. What make a different
Rõ ràng có sự bất tiện khi sử dụng Map

Vấn đề memory có được dọn dẹp hay không đã là sự khác biệt map và weakmap. Vậy lúc nào ta nên dùng WeakMap?

  • Đầu tiên, ta cần một Map để chứa key-value. Tuy nhiên thời gian sử dụng chỉ gói gọn trong một vài dòng code. Tính toán, mapping xong lại không xài tới Map nữa -> Ưu tiên sử dụng WeakMap.
  • Keeping private data about a specific object and only giving access to it to people with a reference to the Map. A more ad-hoc approach is coming with the private-symbols proposal but that’s a long time from now. Đảm bảo an toàn cho dữ liệu, chỉ cho phép access đối với các đối tượng có tham chiếu và cần sử dụng tới WeakMap.

Chắc sẽ còn một vài trường hợp khác WeakMap trở nên hữu ích. Tui sẽ bổ sung cho mấy ông sau.

4. Tham khảo

Thank for your attention – Have a great day – Happy coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm tìm việc IT hấp dẫn trên TopDev