Bất kỳ điểm nào trong việc sử dụng ES6 Map khi các khóa là tất cả các chuỗi?


36

Các khóa đối tượng đơn giản phải là các chuỗi, trong khi một Mapkhóa có thể có bất kỳ loại nào.

Nhưng tôi có ít sử dụng cho việc này trong thực tế. Trong hầu hết các trường hợp, tôi thấy mình sử dụng chuỗi làm khóa. Và có lẽ new Map()là chậm hơn {}. Vì vậy, có bất kỳ lý do khác tại sao nó có thể tốt hơn để sử dụng Mapthay vì một đối tượng đơn giản?


3
MDN , như thường lệ, có một so sánh tốt.
Chris Hayes

1
FYI, Map dường như nhanh hơn cho cả cài đặt và nhận.
mở

@mpen - jsperf không hoạt động. Bạn có chắc chắn map.set('foo', 123)thực hiện nhanh hơn obj.foo = 123? Nếu vậy thì thật đáng ngạc nhiên
callum

@callum Uhh..không, không tích cực. Bạn có thể muốn viết một số bài kiểm tra hiệu suất mới.
mở

Câu trả lời:


42

Có một số lý do tại sao tôi thích sử dụng Maps hơn các đối tượng đơn giản ( {}) để lưu trữ dữ liệu thời gian chạy (cache, v.v.):

  1. Các .sizebất động sản cho phép tôi biết có bao nhiêu mục tồn tại trong Bản đồ này;
  2. Các phương pháp tiện ích khác nhau - .clear(), .forEach(), vv;
  3. Họ cung cấp cho tôi các vòng lặp theo mặc định!

Mọi trường hợp khác, như truyền đối số hàm, lưu cấu hình, v.v., đều được viết bằng các đối tượng đơn giản.

Ngoài ra, hãy nhớ: Đừng cố tối ưu hóa mã của bạn quá sớm. Đừng lãng phí thời gian của bạn để làm điểm chuẩn của đối tượng đơn giản so với Bản đồ trừ khi dự án của bạn đang gặp vấn đề về hiệu suất.


1
Hàm hashcode nhận dạng được Javascript sử dụng là gì?
Pacerier

1
@Pacerier ===:)
gustavohenke

Bản đồ ngày nay nhanh hơn nhiều so với các vật thể đơn giản.
jayarjo

@gustavohenke Điều đó không đúng. Mapsử dụng thuật toán SameValueZero. developer.mozilla.org/en-US/docs/Web/JavaScript/ từ
lolmaus - Andrey Mikhaylov

@ lolmaus-AndreyMikhaylov được rồi, nhưng tôi có nói gì về việc Mapsử dụng cái này hay cái kia không?
gustavohenke

4

Tôi không chắc về điều này, nhưng tôi nghĩ rằng hiệu suất KHÔNG phải là lý do để sử dụng Bản đồ. Hãy xem trang jsperf cập nhật này:

http://jsperf.com/es6-map-vs-object-properIES/73

Có vẻ như (khi xử lý chuỗi ít nhất) các đối tượng nhanh hơn nhiều so với bản đồ cho cài đặt cơ bản và nhận.


2
Đó không phải là cách bạn viết bài kiểm tra hiệu suất.
Qix

6
Đó không phải là cách bạn viết bình luận hữu ích. Xin vui lòng giải thích nếu bạn có một phương pháp thay thế để đề xuất. Điều gì, cụ thể, là sai với cách những bài kiểm tra đã được viết? Họ theo bất kỳ cách nào không hợp lệ hoặc không có ích?
starlogodaniel

9
Ngữ nghĩa / cấu trúc ngôn ngữ đang được kiểm tra thông qua microbenchmark chỉ phải khác nhau bởi một biến. Các thử nghiệm của bạn khác nhau giữa số lần lặp và một vài trong số chúng sẽ được tối ưu hóa nội dung vòng lặp bên trong do kết quả không được sử dụng. Một số thử nghiệm khai báo trước các biến trong khi các biến khác có khai báo biến nội tuyến với vòng lặp for - có thể phát sinh các bất thường về hiệu suất khác nhau.
Qix

1
Ouch, bạn hoàn toàn đúng. Để bảo vệ tôi, phiên bản của tôi là một cải tiến trên phiên bản trước đó, nhưng tôi đã bỏ lỡ cả nội dung khai báo trước và nội dung vòng lặp bên trong đang được tối ưu hóa. Tôi đã làm việc với một đồng nghiệp đã cải thiện dự thảo của mình và tôi nghĩ đã giải quyết được những vấn đề đó: jsperf.com/es6-map-vs-object-properIES/88 . Tuy nhiên, tôi nghĩ rằng nó hợp lệ khi có các kiểu vòng lặp khác nhau cho các cấu trúc dữ liệu khác nhau; trong sử dụng thực tế, mọi người sẽ chọn cấu trúc vòng lặp có hiệu suất tốt nhất và Map và Object có các cấu trúc vòng lặp "tối ưu" khác nhau. Dù sao, cảm ơn cho bắt.
starlogodaniel

Ok tôi thấy bây giờ - chúng từng chậm hơn các đối tượng đơn giản, nhưng đã được tối ưu hóa rất nhiều trong các trình duyệt gần đây.
jayarjo

0

Các câu trả lời khác không đề cập đến một sự khác biệt cuối cùng giữa các đối tượng và Maps:

Đối Maptượng giữ các cặp khóa-giá trị và ghi nhớ thứ tự chèn ban đầu của các khóa .

Do đó, khi lặp qua nó, một đối tượng Map sẽ trả về các khóa theo thứ tự chèn.

Trích dẫn từ MDN , nhấn mạnh của tôi


Đây là lý do chính khiến tôi quyết định sử dụng Maplần đầu tiên trong một dự án gần đây. Tôi đã có một đối tượng bình thường mà tôi cần hiển thị trong một <table>, với mỗi thuộc tính đi theo một hàng cụ thể.

let productPropertyOrder = [ "name", "weight", "price", "stocked" ];

let product =
{
    name: "Lasagne",
    weight: "1kg",
    price: 10,
    stocked: true
}

Tôi đã viết một hàm để biến đổi một đối tượng thành một Mapthứ tự khóa mong muốn:

function objectToMap( obj, order )
{
    let map = new Map();

    for ( const key of order )
    {
        if ( obj.hasOwnProperty( key ) )
        {
            map.set( key, obj[ key ] );
        }
    }

    return map;
}

Sau đó, bản đồ có thể được lặp đi lặp lại theo thứ tự mong muốn:

let productMap = objectToMap( product, productPropertyOrder );

for ( const value of productMap.values() )
{
    let cell = document.createElement( "td" );
    cell.innerText = value;
    row.appendChild( cell );
}

Tất nhiên điều này là một chút giả định bởi vì người ta cũng có thể hiển thị tốt khi lặp qua thứ tự thuộc tính mà không tạo ra Maptrong quá trình:

for ( const key of productPropertyOrder )
{
    if ( product.hasOwnProperty( key ) )
    {
        let value = product[ key ];
        // create cell
    }
}

Nhưng nếu bạn có một loạt các đối tượng như vậy và sẽ hiển thị chúng ở nhiều nơi, thì việc chuyển đổi tất cả chúng thành bản đồ trước tiên có ý nghĩa.

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.