Bản đồ và Đối tượng trong ES6, Sử dụng khi nào?


83

Tham khảo: Bản đồ MDN

Sử dụng bản đồ trên các đối tượng khi các khóa không xác định cho đến thời gian chạy và khi tất cả các khóa là cùng một loại và tất cả các giá trị là cùng một loại.

Sử dụng các đối tượng khi có logic hoạt động trên các phần tử riêng lẻ.

Câu hỏi:

Ví dụ áp dụng về việc sử dụng Bản đồ trên các đối tượng là gì? cụ thể là "khi nào các khóa sẽ không xác định cho đến thời gian chạy?"

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));

Vâng, tôi nhận thấy điều đó. Khi tôi đặt một hàm làm giá trị. @JonathanLonowski bạn có thể nghĩ đến khi tôi nên làm điều đó tho :( nó là khó khăn suy nghĩ của usecases.
Matthew Harwood

7
Bạn có thể sử dụng nó khi bạn nói một phần tử DOM mà bạn muốn liên kết một số dữ liệu với việc sử dụng Đối tượng. Thay vì sử dụng, giả sử ID của phần tử làm khóa trong một đối tượng, bạn có thể sử dụng chính phần tử đó làm khóa trong Bản đồ để bạn không quan tâm liệu phần tử có ID (hoặc bất kỳ số nhận dạng duy nhất nào khác ngoài tham chiếu đối tượng hay không ) hay không.
RobG

1
@RobG chỉ là một bổ sung nhỏ: trong trường hợp đó, nó WeakMapcũng có thể hữu ích.
zerkms

1
Tôi nghĩ rằng điều này gợi ý sử dụng các đối tượng như / cho các bản ghi và Bản đồ cho mọi loại ánh xạ khác. Với bản ghi, tôi muốn nói đến một cấu trúc dữ liệu với một tập hợp các trường cố định, chẳng hạn như một đối tượng người dùng có các trường nameidví dụ.
Felix Kling,

1
Khi tôi đang đọc trang MDN đó, danh sách các trường hợp sử dụng có dấu đầu dòng hữu ích hơn nhiều so với đoạn bạn đã trích dẫn. Chắc chắn liên quan đến câu hỏi được đặt ra trong tiêu đề của bạn.
CodingIntrigue

Câu trả lời:


51

Ví dụ áp dụng về việc sử dụng Bản đồ trên các đối tượng là gì?

Tôi nghĩ rằng bạn đã đưa ra một ví dụ điển hình: Bạn ít nhất cần sử dụng Maps khi bạn đang sử dụng các đối tượng (bao gồm các đối tượng Hàm) làm khóa.

cụ thể là "khi nào các khóa sẽ không xác định cho đến thời gian chạy?"

Bất cứ khi nào chúng không được biết vào thời gian biên dịch. Tóm lại, bạn nên luôn sử dụng a Mapkhi cần thu thập khóa-giá trị . Một chỉ báo tốt rằng bạn cần một bộ sưu tập là khi bạn thêm và xóa động các giá trị khỏi bộ sưu tập và đặc biệt là khi bạn không biết trước các giá trị đó (ví dụ: chúng được đọc từ cơ sở dữ liệu, do người dùng nhập vào, v.v.).

Ngược lại, bạn nên sử dụng các đối tượng khi bạn biết đối tượng có bao nhiêu và thuộc tính nào trong khi viết mã - khi hình dạng của chúng là tĩnh. Như @Felix đã nói: khi bạn cần một bản ghi . Một chỉ báo tốt để cần điều đó là khi các trường có các kiểu khác nhau và khi bạn không bao giờ cần sử dụng ký hiệu dấu ngoặc (hoặc mong đợi một tập hợp giới hạn tên thuộc tính trong đó).


1
Hoặc theo quan điểm khác: Bất cứ khi nào bạn cần lặp qua các thuộc tính của đối tượng của mình ở cấp dữ liệu (ví dụ for..of) thay vì cấp chương trình (ví dụ for..in), hãy sử dụng a Map. Thêm thông tin liên quan đến điều khoản này trong phản hồi này .

Tôi cũng sẽ thêm vào phần bình luận rằng bất cứ lúc nào bạn không biết loại khóa của mình sẽ là loại nào và bạn không mong đợi chuỗi làm kiểu dữ liệu chính, thì hãy sử dụng map stackoverflow.com/questions/32600157/…
Carmine Tambascia

26

Tôi nghĩ rằng với ES2015, Mapchỉ còn lại hai lý do để sử dụng các đối tượng đơn giản:

Khi nào thứ tự tài sản không quan trọng?

  • nếu bạn chỉ có một giá trị duy nhất và một số hàm phải được liên kết rõ ràng với nó (như Promise- là proxy cho giá trị trong tương lai - và then/ catch)
  • nếu bạn có cấu trúc dữ liệu giống như cấu trúc / bản ghi với một tập hợp các thuộc tính tĩnh được biết đến tại "thời gian biên dịch" (thường cấu trúc / bản ghi không thể lặp lại)

Trong tất cả các trường hợp khác, bạn có thể cân nhắc việc sử dụng Map, vì nó bảo toàn thứ tự thuộc tính và tách chương trình (tất cả các thuộc tính được gán cho Mapđối tượng) khỏi mức dữ liệu (tất cả các mục trong Mapchính nó).

Hạn chế của là Mapgì?

  • bạn mất cú pháp chữ đối tượng ngắn gọn
  • bạn cần các trình thay thế tùy chỉnh cho JSON.stringyfy
  • bạn mất cấu trúc hủy, điều này hữu ích hơn với cấu trúc dữ liệu tĩnh

Dòng này khiến tôi rất lo ngại: "nó có thể chậm hơn so với các đối tượng thuần túy, giống như bản đồ băm". Tôi đã nghĩ đến việc thay thế tất cả các đối tượng của mình bằng bản đồ vì cải thiện hiệu suất. Nhưng bạn nói nó chậm hơn ...
mesqueeb

1
Bạn đúng. Mapcó lẽ nhanh hơn, vì nó hoàn toàn dựa trên một hàm băm, trong khi Objectphức tạp hơn một chút. Cảm ơn!

11

Sử dụng bản đồ trên các đối tượng khi các khóa không xác định cho đến thời gian chạy và khi tất cả các khóa là cùng một loại và tất cả các giá trị là cùng một loại.

Tôi không biết tại sao ai đó lại viết một cái gì đó rõ ràng là sai. Tôi phải nói rằng, ngày càng có nhiều người tìm thấy nội dung sai và / hoặc có vấn đề trên MDN ngày càng nhiều.

Không có gì trong câu đó là đúng. Lý do chính để sử dụng bản đồ là khi bạn muốn các khóa có giá trị đối tượng. Ý tưởng rằng các giá trị phải cùng một kiểu là vô lý - mặc dù tất nhiên chúng có thể là như vậy. Ý tưởng rằng người ta không nên sử dụng các đối tượng khi các khóa chưa biết cho đến khi thời gian chạy cũng vô lý như nhau.


1
Tôi không thấy có gì là vô lý về ý tưởng? Khi bạn cần các bộ sưu tập, chúng thường được nhập đúng cách (tất nhiên có thể có ngoại lệ). Ngoài ra, tôi nghĩ rằng không sử dụng các đối tượng cho các bộ sưu tập nữa (khi Mapcó sẵn) là lời khuyên tốt.
Bergi

Đối với việc các bộ sưu tập thường được đánh đúng là khác biệt về mặt logic với việc nói rằng một cái gì đó được gõ đúng phải là một tập hợp.

1
Vâng, tôi nghĩ nó hơi kỳ quặc, nhưng ý tưởng là tốt. Tôi đoán rằng họ nghĩ rằng "các khóa không xác định cho đến khi thời gian chạy" đã tạo ra một bộ sưu tập. Bất kỳ ý tưởng cho một cụm từ tốt hơn?
Bergi

1
Đã đồng ý. MDN có tài liệu rất tốt, nhưng họ nên bám vào tài liệu API và không cố gắng đưa ra lời khuyên lập trình.
AlexG

5

Một trong những điểm khác biệt giữa MapObjectlà:

Mapcó thể sử dụng kiểu dữ liệu phức tạp làm khóa của nó. như thế này:

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

coi chừng: Đối với kiểu dữ liệu phức tạp, Nếu bạn muốn nhận giá trị, bạn phải chuyển cùng một tham chiếu với khóa.

Object, nó chỉ chấp nhận kiểu dữ liệu đơn giản ( number, string) làm khóa của nó.

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}

2

Câu hỏi này là một bản sao của nhưng cho đến khi nó đóng cửa, đây là câu trả lời của tôi từ đó :

Ngoài các câu trả lời khác, tôi nhận thấy rằng Maps khó sử dụng và dài dòng hơn để vận hành với các đối tượng.

obj[key] += x
// vs.
map.set(map.get(key) + x)

Điều này rất quan trọng, vì mã ngắn hơn thì đọc nhanh hơn, diễn đạt trực tiếp hơn và lưu giữ trong đầu của lập trình viên tốt hơn .

Một khía cạnh khác: bởi vì set () trả về bản đồ, không phải giá trị, nên không thể thực hiện chuỗi các phép gán.

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

Gỡ lỗi bản đồ cũng khó hơn. Dưới đây, bạn thực sự không thể nhìn thấy những phím nào trong bản đồ. Bạn phải viết mã để làm điều đó.

Chúc bạn may mắn khi đánh giá Trình lặp bản đồ

Các đối tượng có thể được đánh giá bởi bất kỳ IDE nào:

WebStorm đánh giá một đối tượng


6
Điều này không trả lời cho câu hỏi " Ví dụ áp dụng về việc sử dụng Bản đồ trên các đối tượng là gì? "
Bergi

6
Vui lòng không đăng chéo câu trả lời của bạn. Và không, câu hỏi không phải là một bản sao.
Bergi

1

Objects tương tự như Maps ở chỗ cả hai đều cho phép bạn đặt khóa cho các giá trị, truy xuất các giá trị đó, xóa khóa và phát hiện xem có thứ gì đó được lưu trữ trong khóa hay không. Bởi vì điều này (và bởi vì không có lựa chọn thay thế tích hợp sẵn), Objects đã được sử dụng trong Maplịch sử; tuy nhiên, có những điểm khác biệt quan trọng khiến việc sử dụng được Mapưu tiên trong một số trường hợp nhất định:

  • Các khóa của an ObjectStrings và Symbols, trong khi chúng có thể là bất kỳ giá trị nào của a Map, bao gồm các hàm, đối tượng và bất kỳ nguyên thủy nào.
  • Các khóa trong Mapđược sắp xếp thứ tự trong khi các khóa được thêm vào đối tượng thì không. Do đó, khi lặp lại nó, một Mapđối tượng trả về các khóa theo thứ tự chèn.
  • Bạn có thể Mapdễ dàng nhận được kích thước của một thuộc sizetính, trong khi số lượng thuộc tính trong một Objectphải được xác định theo cách thủ công.
  • A Maplà một tệp có thể lặp lại và do đó có thể được lặp lại trực tiếp, trong khi việc lặp lại trên một Objectyêu cầu lấy các khóa của nó theo một cách nào đó và lặp lại chúng.
  • An Objectcó một nguyên mẫu, vì vậy có các khóa mặc định trong bản đồ có thể va chạm với các khóa của bạn nếu bạn không cẩn thận. Đối với ES5, điều này có thể được bỏ qua bằng cách sử dụng map = Object.create(null), nhưng điều này hiếm khi được thực hiện.
  • A Mapcó thể hoạt động tốt hơn trong các tình huống liên quan đến việc bổ sung và loại bỏ các cặp khóa thường xuyên.

MDN

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.