Chúng ta có thể sử dụng đối tượng làm khóa trong javascript hashmap không?

Trong JavaScript, các đối tượng rất tiện dụng. Chúng cho phép chúng tôi dễ dàng nhóm nhiều phần dữ liệu lại với nhau. Sau ES6, chúng tôi đã có một bổ sung mới cho ngôn ngữ -

const hashMap = {}
0. Ở nhiều khía cạnh, có vẻ như một
const hashMap = {}
1 có khả năng hơn với giao diện hơi vụng về. Tuy nhiên, hầu hết mọi người vẫn tiếp cận các đối tượng khi họ cần bản đồ băm và chỉ chuyển sang sử dụng
const hashMap = {}
0 khi họ nhận ra rằng các khóa không thể chỉ là các chuỗi cho các trường hợp sử dụng của họ. Kết quả là,
const hashMap = {}
0 vẫn chưa được sử dụng nhiều trong cộng đồng JavaScript ngày nay

Trong bài đăng này, tôi sẽ chia nhỏ tất cả các lý do khi bạn nên cân nhắc sử dụng thêm

const hashMap = {}
0 và các đặc điểm hiệu suất của nó với điểm chuẩn

Trong JavaScript, Object là một thuật ngữ khá rộng. Hầu hết mọi thứ đều có thể là một đối tượng, ngoại trừ hai loại dưới cùng -

const hashMap = {}
5 và
const hashMap = {}
6. Trong bài đăng trên blog này, Đối tượng chỉ đề cập đến các đối tượng cũ đơn giản, được phân định bằng dấu ngoặc nhọn bên trái
const hashMap = {}
7 và dấu ngoặc nhọn bên phải
const hashMap = {}
8

TL; DR

  • Sử dụng
    const hashMap = {}
    
    1 cho các bản ghi mà bạn có số lượng thuộc tính/trường cố định và hữu hạn được biết đến tại thời điểm tác giả, chẳng hạn như đối tượng cấu hình. Và bất cứ thứ gì dùng một lần nói chung
  • Sử dụng
    const hashMap = {}
    
    0 cho từ điển hoặc bản đồ băm mà bạn có số lượng mục nhập thay đổi, với các bản cập nhật thường xuyên, có thể không biết các khóa của chúng tại thời điểm tác giả, chẳng hạn như một
  • Theo , trừ khi các khóa là các chuỗi số nguyên nhỏ, thì
    const hashMap = {}
    
    0 thực sự có hiệu suất cao hơn so với
    const hashMap = {}
    
    1 về tốc độ chèn, xóa và lặp, đồng thời nó tiêu tốn ít bộ nhớ hơn so với một đối tượng có cùng kích thước

Tại sao
const hashMap = {}
1 không đáp ứng được trường hợp sử dụng bản đồ băm

Có lẽ nhược điểm rõ ràng nhất của việc sử dụng các đối tượng cho bản đồ băm là các đối tượng chỉ cho phép các khóa là chuỗi và ký hiệu. Bất kỳ loại nào khác sẽ được chuyển thành chuỗi hoàn toàn thông qua phương thức

const hashMap = {}
44

const hashMap = {}
5

Quan trọng hơn, việc sử dụng các đối tượng cho bản đồ băm có thể gây nhầm lẫn và nguy cơ bảo mật

thừa kế không mong muốn

Trước ES6, cách duy nhất để lấy bản đồ băm là tạo một đối tượng trống

const hashMap = {}

Tuy nhiên, khi tạo, đối tượng này không còn trống nữa. Mặc dù

const hashMap = {}
45 được tạo bằng một đối tượng trống theo nghĩa đen, nhưng nó sẽ tự động kế thừa từ
const hashMap = {}
46. Đó là lý do tại sao chúng ta có thể gọi các phương thức như
const hashMap = {}
47,
const hashMap = {}
44,
const hashMap = {}
49 trên
const hashMap = {}
45 mặc dù chúng ta chưa bao giờ định nghĩa rõ ràng các phương thức đó trên đối tượng

Do kế thừa nguyên mẫu, giờ đây chúng tôi có hai loại thuộc tính được kết hợp. thuộc tính sống trong chính đối tượng, tôi. e. các thuộc tính riêng của nó và các thuộc tính tồn tại trong chuỗi nguyên mẫu, tôi. e. tài sản kế thừa. Do đó, chúng tôi cần kiểm tra bổ sung [e. g.

const hashMap = {}
47] để đảm bảo rằng một thuộc tính nhất định thực sự do người dùng cung cấp, trái ngược với thuộc tính kế thừa từ nguyên mẫu

Ngoài ra, do cơ chế phân giải thuộc tính hoạt động như thế nào trong JavaScript, bất kỳ thay đổi nào đối với

const hashMap = {}
46 trong thời gian chạy sẽ gây ra hiệu ứng gợn sóng trong tất cả các đối tượng. Điều này mở ra cơ hội cho các cuộc tấn công ô nhiễm nguyên mẫu, đây có thể là một vấn đề bảo mật nghiêm trọng đối với các ứng dụng JavaScript lớn

May mắn thay, chúng ta có thể giải quyết vấn đề này bằng cách sử dụng

const hashMap = {}
53, điều này tạo ra một đối tượng không kế thừa gì từ
const hashMap = {}
46

tên va chạm

Khi các thuộc tính riêng của một đối tượng có xung đột tên với các thuộc tính trên nguyên mẫu của nó, nó sẽ phá vỡ các kỳ vọng và do đó làm hỏng chương trình của bạn

Ví dụ: chúng ta có hàm

const hashMap = {}
55 chấp nhận một đối tượng

const hashMap = {}
4

Có một mối nguy hiểm về độ tin cậy trong

const hashMap = {}
56. đưa ra cách thức hoạt động của cơ chế phân giải thuộc tính trong JavaScript, nếu
const hashMap = {}
57 chứa thuộc tính do người dùng cung cấp có cùng tên
const hashMap = {}
47, thì điều đó sẽ che phủ
const hashMap = {}
59. Do đó, chúng tôi không biết phương thức nào sẽ được gọi chính xác trong thời gian chạy

Một số chương trình phòng thủ có thể được thực hiện để ngăn chặn điều này. Ví dụ: chúng ta có thể "mượn"

const hashMap = {}
47 "thực" từ
const hashMap = {}
46 để thay thế

const hashMap = {}
5

Một cách ngắn hơn có thể gọi phương thức trên một đối tượng theo nghĩa đen như trong

const hashMap = {}
62 tuy nhiên nó vẫn còn khá cồng kềnh. Đó là lý do tại sao có một phương thức tĩnh mới được thêm vào
const hashMap = {}
63

Công thái học dưới mức tối ưu

const hashMap = {}
1 không cung cấp công thái học đầy đủ để được sử dụng làm bản đồ băm. Nhiều tác vụ phổ biến không thể được thực hiện bằng trực giác

kích thước

const hashMap = {}
1 không đi kèm với API tiện dụng để lấy kích thước, tôi. e. số lượng tài sản. Và có những sắc thái đối với những gì tạo nên kích thước của một đối tượng

  • nếu bạn chỉ quan tâm đến chuỗi, vô số khóa, thì bạn có thể chuyển đổi các khóa thành một mảng với ________ 366 và nhận được ________ 367 của nó
  • nếu bạn muốn tính đến các khóa chuỗi không thể đếm được, thì bạn phải sử dụng
    const hashMap = {}
    
    68 để lấy danh sách các khóa và lấy độ dài của nó
  • nếu bạn quan tâm đến các phím ký hiệu, bạn có thể sử dụng
    const hashMap = {}
    
    69 để hiển thị các phím ký hiệu. Hoặc bạn có thể sử dụng
    const hashMap = {}
    
    40 để nhận cả khóa chuỗi và khóa ký hiệu cùng một lúc, bất kể nó có đếm được hay không

Tất cả các tùy chọn trên có độ phức tạp thời gian chạy là

const hashMap = {}
41 vì trước tiên chúng tôi phải xây dựng một mảng khóa trước khi chúng tôi có thể nhận được độ dài của nó

lặp đi lặp lại

Vòng lặp qua các đối tượng chịu sự phức tạp tương tự

Chúng ta có thể sử dụng vòng lặp

const hashMap = {}
42 cũ tốt. Nhưng nó tiết lộ vô số thuộc tính kế thừa

const hashMap = {}
6

Chúng tôi không thể sử dụng

const hashMap = {}
43 với một đối tượng vì theo mặc định, nó không thể lặp lại, trừ khi chúng tôi xác định rõ ràng phương thức
const hashMap = {}
44 trên đó

Chúng ta có thể sử dụng

const hashMap = {}
45,
const hashMap = {}
46 và
const hashMap = {}
47 để lấy danh sách các khóa chuỗi [hoặc/và giá trị] có thể đếm được và lặp lại qua đó thay vào đó, điều này giới thiệu một bước bổ sung với chi phí hoạt động

Cuối cùng, thứ tự chèn không được tôn trọng đầy đủ. Trong hầu hết các trình duyệt, các khóa số nguyên được sắp xếp theo thứ tự tăng dần và được ưu tiên hơn các khóa chuỗi ngay cả khi các khóa chuỗi được chèn trước các khóa số nguyên

const hashMap = {}
4

xa lạ

Không có cách nào dễ dàng để xóa tất cả các thuộc tính khỏi một đối tượng, bạn phải xóa từng thuộc tính một bằng toán tử

const hashMap = {}
48, vốn được biết đến là chậm. Tuy nhiên, điểm chuẩn của tôi cho thấy rằng hiệu suất của nó thực sự không chậm hơn một bậc so với
const hashMap = {}
49. Thêm về điều đó sau

kiểm tra sự tồn tại của tài sản

Cuối cùng, chúng ta không thể dựa vào ký hiệu dấu chấm/dấu ngoặc để kiểm tra sự tồn tại của một thuộc tính vì bản thân giá trị đó có thể được đặt là

const hashMap = {}
6. Thay vào đó chúng ta phải sử dụng
const hashMap = {}
59 hoặc
const hashMap = {}
63

const hashMap = {}
9

Bản đồ cho Bản đồ băm

ES6 mang lại cho chúng tôi

const hashMap = {}
0. Nó phù hợp hơn nhiều cho trường hợp sử dụng bản đồ băm

Trước hết, không giống như ________ 01 chỉ cho phép các khóa là chuỗi và ký hiệu, ________ 00 hỗ trợ các khóa thuộc mọi loại dữ liệu

Tuy nhiên, nếu bạn đang sử dụng

const hashMap = {}
0 để lưu trữ siêu dữ liệu cho các đối tượng, thì bạn nên sử dụng
const hashMap = {}
97 để tránh rò rỉ bộ nhớ

Nhưng quan trọng hơn,

const hashMap = {}
0 cung cấp sự tách biệt rõ ràng giữa dữ liệu do người dùng xác định và dữ liệu chương trình tích hợp sẵn, với chi phí bổ sung là
const hashMap = {}
99 để truy xuất các mục nhập

const hashMap = {}
0 cũng cung cấp công thái học tốt hơn. Một
const hashMap = {}
0 là một iterable theo mặc định. Điều đó có nghĩa là bạn có thể lặp lại bản đồ một cách dễ dàng với
const hashMap = {}
43 và thực hiện những việc như sử dụng tính năng phá hủy lồng nhau để lấy mục nhập đầu tiên khỏi bản đồ

const hashMap = {}
0

Trái ngược với

const hashMap = {}
1,
const hashMap = {}
0 cung cấp các API chuyên dụng cho các tác vụ phổ biến khác nhau

  • const hashMap = {}
    
    05 kiểm tra sự tồn tại của một mục nhất định, ít khó xử hơn so với việc phải
    const hashMap = {}
    
    59 /
    const hashMap = {}
    
    63 trên các đối tượng
  • const hashMap = {}
    
    99 trả về giá trị được liên kết với khóa được cung cấp. Người ta có thể cảm thấy điều này rườm rà hơn ký hiệu dấu chấm hoặc ký hiệu dấu ngoặc trên các đối tượng. Tuy nhiên, nó cung cấp sự tách biệt rõ ràng giữa dữ liệu người dùng và phương thức tích hợp
  • const hashMap = {}
    
    09 trả về số lượng mục nhập trong một
    const hashMap = {}
    
    0 và nó rõ ràng là người chiến thắng trong các thao tác mà bạn phải thực hiện để có được kích thước của một đối tượng. Bên cạnh đó, nó nhanh hơn nhiều
  • const hashMap = {}
    
    91 loại bỏ tất cả các mục trong một
    const hashMap = {}
    
    0 và nó nhanh hơn nhiều so với toán tử
    const hashMap = {}
    
    48

Hiệu suất hoành tráng

Dường như có một niềm tin chung trong cộng đồng JavaScript rằng hầu hết các phần của

const hashMap = {}
0 nhanh hơn
const hashMap = {}
1. Có những người tuyên bố đã thấy hiệu suất tăng đáng kể khi chuyển từ
const hashMap = {}
1 sang
const hashMap = {}
0

Kinh nghiệm mài LeetCode của tôi dường như xác nhận niềm tin này. LeetCode cung cấp một lượng dữ liệu khổng lồ dưới dạng các trường hợp thử nghiệm cho giải pháp của bạn và sẽ hết thời gian nếu giải pháp của bạn mất quá nhiều thời gian. Những câu hỏi như thế này chỉ hết thời gian nếu bạn sử dụng

const hashMap = {}
1, nhưng không phải trên
const hashMap = {}
0

Tuy nhiên, tôi tin rằng chỉ cần nói "

const hashMap = {}
0 nhanh hơn
const hashMap = {}
1" là đơn giản. Phải có một số sắc thái mà tôi muốn tìm hiểu bản thân mình. Vì vậy. Tôi đã tạo một ứng dụng nhỏ để chạy một số điểm chuẩn

Tuyên bố miễn trừ trách nhiệm quan trọng

Tôi không khẳng định mình hoàn toàn hiểu cách V8 hoạt động bí mật để tối ưu hóa

const hashMap = {}
0 mặc dù tôi đã nhiều lần cố gắng đọc các bài đăng trên blog và xem qua mã nguồn C++. Đo điểm chuẩn mạnh mẽ hoàn hảo là khó và hầu hết chúng ta chưa bao giờ trải qua bất kỳ hình thức đào tạo nào về đo điểm chuẩn hoặc diễn giải kết quả. Tôi càng làm nhiều điểm chuẩn, tôi càng cảm thấy nó giống như một câu chuyện về những người mù và một con voi. Vì vậy, hãy coi thường mọi điều tôi đang nói ở đây về hiệu suất. Bạn sẽ cần kiểm tra những thay đổi như vậy với ứng dụng của mình trong môi trường sản xuất để biết chắc chắn liệu có hiệu suất thực tế đạt được từ việc sử dụng
const hashMap = {}
0 so với
const hashMap = {}
1 hay không

Chi tiết triển khai điểm chuẩn

Ứng dụng này có một bảng hiển thị tốc độ chèn, lặp lại và xóa được đo trên

const hashMap = {}
1 và
const hashMap = {}
0

Hiệu suất của thao tác chèn và lặp được đo bằng thao tác trên giây. Tôi đã viết một hàm tiện ích

const hashMap = {}
57 chạy lặp lại hàm đích cho đến ngưỡng thời gian tối thiểu đã chỉ định [i. e. trường đầu vào
const hashMap = {}
58 trên giao diện người dùng] đã đạt được. Nó trả về số lần trung bình một chức năng như vậy được thực thi mỗi giây

const hashMap = {}
9

Đối với việc xóa, tôi chỉ đơn giản là đo thời gian sử dụng toán tử

const hashMap = {}
48 để xóa tất cả các thuộc tính khỏi một đối tượng và so sánh nó với thời gian của
const hashMap = {}
49 cho một
const hashMap = {}
0 có cùng kích thước. Tôi có thể sử dụng
const hashMap = {}
91 nhưng nó đánh bại mục đích của điểm chuẩn vì tôi biết chắc chắn rằng nó sẽ nhanh hơn rất nhiều

Trong ba thao tác này, tôi chú ý nhiều hơn đến thao tác chèn vì nó có xu hướng là thao tác phổ biến nhất mà tôi thực hiện trong công việc hàng ngày của mình. Đối với hiệu suất lặp, thật khó để đưa ra một điểm chuẩn bao gồm tất cả vì có nhiều biến thể lặp khác nhau mà chúng ta có thể thực hiện trên một đối tượng nhất định. Ở đây tôi chỉ đo vòng lặp

const hashMap = {}
42

Tôi đã sử dụng ba loại chìa khóa ở đây

  1. chuỗi, e. g.
    const hashMap = {}
    
    04
  2. chuỗi số nguyên, e. g.
    const hashMap = {}
    
    05
  3. chuỗi số được tạo bởi
    const hashMap = {}
    
    06, e. g.
    const hashMap = {}
    
    07

Tất cả các khóa được tạo ngẫu nhiên để chúng tôi không nhấn vào bộ đệm nội tuyến do V8 triển khai. Tôi cũng chuyển đổi rõ ràng các khóa số nguyên và số thành chuỗi bằng cách sử dụng

const hashMap = {}
44 trước khi thêm chúng vào các đối tượng để tránh chi phí truyền ngầm

Cuối cùng, trước khi điểm chuẩn bắt đầu, cũng có một giai đoạn khởi động trong ít nhất 100 mili giây trong đó chúng tôi liên tục tạo các đối tượng và bản đồ mới sẽ bị loại bỏ ngay lập tức

Tôi đặt mã trên CodeSandbox nếu bạn muốn chơi với nó

Tôi đã bắt đầu với

const hashMap = {}
1 và
const hashMap = {}
0 với kích thước 100 thuộc tính/mục nhập, cho đến hết 5000000 và để mỗi loại hoạt động tiếp tục chạy trong 10000 mili giây để xem chúng hoạt động như thế nào với nhau. Đây là những phát hiện của tôi

Tại sao chúng tôi dừng lại khi số lượng mục nhập đạt 5000000?

Bởi vì nó lớn bằng một đối tượng có thể nhận được trong JavaScript. Theo , một kỹ sư V8 đang hoạt động trên StackOverflow, "nếu các phím là chuỗi, một đối tượng thông thường sẽ trở nên chậm chạp một cách bất thường sau ~8. Các yếu tố 3M [vì lý do kỹ thuật. một trường bit nhất định rộng 23 bit và sử dụng đường dẫn dự phòng rất chậm khi vượt quá]. "

phím chuỗi

Nói chung, khi các khóa là chuỗi [không phải số],

const hashMap = {}
0 hoạt động tốt hơn
const hashMap = {}
1 trên tất cả các thao tác

Nhưng điều khó hiểu là khi số lượng mục nhập không thực sự lớn [dưới 100000], thì tốc độ chèn của

const hashMap = {}
0 nhanh gấp đôi so với
const hashMap = {}
1, nhưng khi kích thước tăng lên trên 100000, khoảng cách về hiệu suất bắt đầu thu hẹp lại

Tôi đã tạo một số biểu đồ để minh họa rõ hơn những phát hiện của mình

Biểu đồ trên cho thấy tỷ lệ chèn giảm như thế nào [trục y] khi số lượng mục nhập tăng lên [trục x]. Tuy nhiên do trục x mở rộng quá rộng [từ 100 đến 1000000] nên khó nhận biết được khoảng cách giữa 2 đường này

Sau đó, tôi đã sử dụng thang logarit để xử lý dữ liệu và tạo biểu đồ bên dưới

Bạn có thể nói rõ ràng hai dòng đang hội tụ

Tôi đã tạo một biểu đồ khác biểu thị tốc độ chèn của

const hashMap = {}
0 nhanh hơn bao nhiêu so với
const hashMap = {}
1. Bạn có thể thấy
const hashMap = {}
0 bắt đầu nhanh hơn khoảng 2 lần so với
const hashMap = {}
1. Sau đó, theo thời gian, khoảng cách hiệu suất bắt đầu thu hẹp lại. Cuối cùng,
const hashMap = {}
0 chỉ nhanh hơn 30% khi kích thước tăng lên 5000000

Hầu hết chúng ta sẽ không bao giờ có hơn 1 triệu mục trong một đối tượng hoặc bản đồ. Với kích thước vài trăm hoặc hàng nghìn mục nhập,

const hashMap = {}
0 có hiệu suất ít nhất gấp đôi so với
const hashMap = {}
1. Do đó, chúng ta có nên để nó ở đó và bắt đầu tái cấu trúc cơ sở mã của mình bằng cách dốc toàn lực vào
const hashMap = {}
0 không?

Tuyệt đối không. hoặc ít nhất là không kỳ vọng rằng ứng dụng của chúng tôi sẽ nhanh hơn gấp 2 lần. Hãy nhớ rằng chúng tôi chưa khám phá các loại khóa khác. Chúng ta hãy xem các khóa số nguyên

phím số nguyên

Lý do tôi đặc biệt muốn chạy điểm chuẩn trên các đối tượng có khóa số nguyên là V8 tối ưu hóa bên trong và lưu trữ chúng trong một mảng riêng biệt có thể được truy cập tuyến tính và liên tục. Tuy nhiên, tôi không thể tìm thấy bất kỳ tài nguyên nào xác nhận rằng nó sử dụng cùng một loại tối ưu hóa cho những năm

const hashMap = {}
0

Trước tiên hãy thử các khóa số nguyên trong phạm vi [0, 1000]

Đúng như tôi mong đợi, lần này

const hashMap = {}
1 vượt trội hơn
const hashMap = {}
0. Chúng nhanh hơn 65% so với bản đồ về tốc độ chèn và nhanh hơn 16% để lặp lại

Hãy mở rộng phạm vi để số nguyên tối đa trong các khóa là 1200

Có vẻ như bây giờ

const hashMap = {}
0 s đang bắt đầu nhanh hơn một chút so với các đối tượng để chèn và nhanh hơn 5 lần để lặp lại

Bây giờ chúng tôi chỉ tăng phạm vi của các phím số nguyên chứ không phải kích thước thực của

const hashMap = {}
1 và
const hashMap = {}
0. Hãy tăng kích thước để xem điều đó ảnh hưởng đến hiệu suất như thế nào

Khi kích thước của 1000 thuộc tính,

const hashMap = {}
1 sẽ nhanh hơn 70% so với
const hashMap = {}
0 khi chèn và chậm hơn 2 lần khi lặp lại

Tôi đã chơi với một loạt các kết hợp khác nhau của kích thước

const hashMap = {}
1/
const hashMap = {}
0 và phạm vi khóa số nguyên và không thể tìm ra một mẫu rõ ràng. Nhưng xu hướng chung mà tôi đang thấy là, khi kích thước tăng lên, với một số nguyên nhỏ tương đối là khóa, các đối tượng có thể hoạt động hiệu quả hơn
const hashMap = {}
0 về mặt chèn, luôn gần giống như xóa và chậm hơn 4 hoặc 5 lần . Ngưỡng của các khóa số nguyên tối đa mà tại đó các đối tượng bắt đầu chậm hơn để chèn tăng theo kích thước của các đối tượng. Ví dụ: khi đối tượng chỉ có 100 mục nhập, ngưỡng là 1200;

phím số

Cuối cùng, chúng ta hãy xem loại phím cuối cùng - phím số

Về mặt kỹ thuật, các khóa số nguyên trước đây cũng là số. Ở đây, các phím số đề cập cụ thể đến các chuỗi số được tạo bởi

const hashMap = {}
06

Các kết quả tương tự với các trường hợp khóa chuỗi đó. Các

const hashMap = {}
0 bắt đầu nhanh hơn nhiều so với các đối tượng [chèn và xóa nhanh hơn 2 lần, lặp lại nhanh hơn 4-5 lần], nhưng delta ngày càng nhỏ hơn khi chúng tôi tăng kích thước

Còn đối tượng/bản đồ lồng nhau thì sao?

Bạn có thể nhận thấy rằng tôi chỉ nói về các vật thể phẳng và bản đồ chỉ có một chiều sâu. Tôi đã thêm một số chi tiết nhưng tôi thấy rằng các đặc điểm hiệu suất phần lớn vẫn giữ nguyên miễn là tổng số mục nhập là như nhau, bất kể chúng tôi có bao nhiêu cấp độ lồng nhau

Ví dụ: với

const hashMap = {}
36 là 100 và
const hashMap = {}
37 là 3, chúng tôi có tổng số một triệu mục [100 * 100 * 100]. Kết quả gần như giống nhau so với việc chỉ có
const hashMap = {}
38 cho chiều rộng và 1 cho
const hashMap = {}
37

Sử dụng bộ nhớ

Một khía cạnh quan trọng khác của điểm chuẩn là sử dụng bộ nhớ

Vì tôi không có quyền kiểm soát trình thu gom rác trong môi trường trình duyệt, nên tôi quyết định chạy điểm chuẩn trong Node

Tôi đã tạo một tập lệnh nhỏ để đo mức sử dụng bộ nhớ tương ứng của chúng với bộ sưu tập rác đầy đủ được kích hoạt thủ công trong mỗi phép đo. Chạy nó với

const hashMap = {}
40 và tôi nhận được kết quả như sau

const hashMap = {}
5

Rõ ràng là

const hashMap = {}
0 tiêu thụ ít bộ nhớ hơn
const hashMap = {}
1 ở bất kỳ đâu từ 20% đến 50%, điều này không có gì ngạc nhiên vì
const hashMap = {}
0 không lưu trữ các bộ mô tả thuộc tính như
const hashMap = {}
44/
const hashMap = {}
45/
const hashMap = {}
46 giống như
const hashMap = {}
1.

Phần kết luận

Vì vậy, những gì chúng ta lấy đi từ tất cả điều này?

  • const hashMap = {}
    
    0 nhanh hơn
    const hashMap = {}
    
    1 trừ khi bạn có số nguyên nhỏ, khóa được lập chỉ mục theo mảng và tiết kiệm bộ nhớ hơn
  • Sử dụng
    const hashMap = {}
    
    0 nếu bạn cần một bản đồ băm được cập nhật thường xuyên; . e. bản ghi], và coi chừng những cạm bẫy đi kèm với kế thừa nguyên mẫu

Nếu bạn biết chi tiết về cách V8 tối ưu hóa chính xác

const hashMap = {}
0 hoặc chỉ muốn chỉ ra những sai sót trong điểm chuẩn của tôi, hãy liên hệ với tôi. Tôi sẽ vui lòng cập nhật bài đăng này dựa trên thông tin của bạn

Lưu ý về khả năng tương thích của trình duyệt

const hashMap = {}
0 là một tính năng của ES6. Hiện tại, hầu hết chúng ta không nên lo lắng về khả năng tương thích của nó trừ khi bạn đang nhắm mục tiêu cơ sở người dùng với một số trình duyệt cũ, thích hợp. Ý tôi là "cũ" hơn IE 11 vì ngay cả IE 11 cũng hỗ trợ
const hashMap = {}
0 và tại thời điểm này IE 11 đã chết. Theo mặc định, chúng ta không nên dịch mã và thêm polyfill vào mục tiêu ES5 một cách thiếu suy nghĩ, bởi vì nó không chỉ làm tăng kích thước gói của bạn mà còn chạy chậm hơn so với JavaScript hiện đại. Quan trọng nhất, nó phạt 99. 999% người dùng của bạn sử dụng trình duyệt hiện đại

Ngoài ra, chúng tôi không phải bỏ hỗ trợ cho các trình duyệt cũ - cung cấp mã cũ qua

const hashMap = {}
55 bằng cách cung cấp các gói dự phòng để chúng tôi có thể tránh làm giảm trải nghiệm của khách truy cập với các trình duyệt hiện đại. Tham khảo Chuyển sang JavaScript hiện đại nếu bạn cần thuyết phục hơn

Ngôn ngữ JavaScript đang phát triển và nền tảng ngày càng tốt hơn trong việc tối ưu hóa JavaScript hiện đại. Chúng ta không nên sử dụng khả năng tương thích của trình duyệt như một cái cớ để bỏ qua tất cả những cải tiến đã được thực hiện

Tôi có thể sử dụng đối tượng làm khóa trong HashMap không?

Có, chúng ta có thể sử dụng bất kỳ đối tượng nào làm khóa trong Bản đồ trong java nhưng chúng ta cần ghi đè các phương thức equals[] và hashCode[] của lớp đối tượng đó.

Bản đồ JavaScript có thể có đối tượng làm khóa không?

Với bản đồ, tất cả các kiểu gốc [chuỗi, số, boolean, không xác định, null, đối tượng] đều có thể là khóa

Một đối tượng có thể là một khóa trong từ điển JavaScript không?

Khóa từ điển JavaScript . Object keys can only be strings, and even though a developer can use other data types to set keys, JavaScript will convert them to a string value.

Khóa đối tượng có thể là mảng không?

Đối tượng. keys[] trả về một mảng gồm vô số tên thuộc tính khóa chuỗi của một đối tượng nhất định .

Chủ Đề