LocalStorage.getItem ('item') có tốt hơn localStorage.item hoặc localStorage ['item'] không?


84

Gần đây tôi đã đặt một câu hỏi về LocalStorage . Đang sử dụng JSON.parse(localStorage.item)JSON.parse(localStorage['item'])không hoạt động để trả lại NULLkhi mục chưa được đặt.

Tuy nhiên, JSON.parse(localStorage.getItem('item')đã làm việc. Và hóa ra, JSON.parse(localStorage.testObject || null)cũng hoạt động.

Một trong những nhận xét về cơ bản nói rằng localStorage.getItem()localStorage.setItem()nên luôn được ưu tiên:

Getter và setter cung cấp một cách tương thích nhất quán, tiêu chuẩn hóa và trình duyệt chéo để làm việc với api LS và nên luôn được ưu tiên hơn các cách khác. - Christoph

Tôi dần thích sử dụng ký hiệu dấu chấm và dấu ngoặc đơn cho localStorage, nhưng tôi tò mò muốn biết những người khác đảm nhận điều này. LocalStorage.getItem ('item') có tốt hơn localStorage.item hoặc localStorage ['item'] HOẶC miễn là chúng hoạt động được các ký hiệu viết tắt là được?


Tôi tin rằng Christoph đã đưa ra lý lẽ của mình khá rõ ràng. getItemsetItemlà cách thức hoạt động được chuẩn hóa .
Fabrício Matté

1
Tôi hiểu rồi. Hơi quá buồn ngủ khi đọc lướt qua các đề xuất đó, nhưng vì API webstorage này tương đối mới, cá nhân tôi muốn gắn bó với các phương pháp getItem/ tài liệu đúng cách setItem. Tôi sẽ đọc lại các thông số kỹ thuật sau, nhưng cách duy nhất để trả lời câu hỏi của bạn không thành công là thực hiện trong suốt quá trình thử nghiệm trên tất cả các trình duyệt chính.
Fabrício Matté

4
Đặc tả cho biết "Tên thuộc tính được hỗ trợ trên một đối tượng Storage là các khóa của mỗi cặp khóa / giá trị hiện có trong danh sách được liên kết với đối tượng." Điều đó cũng không làm cho localStorage.itemtiêu chuẩn hóa?
Barmar

2
@Barmar Trả lời hơi muộn, nhưng sau khi thấy rất nhiều bản sao của câu hỏi này và quay lại đây, tôi sẽ trả lời rằng bạn hoàn toàn đúng. Tuy nhiên, tôi khuyên bạn nên sử dụng lại getItem/ setItemvì các phương thức này không xung đột với các thuộc tính hiện có của localStorageđối tượng. Ví dụ: localStorage.setItem('getItem', 'blah'); console.log(localStorage.getItem('getItem'));hoạt động, trong khi localStorage.getItem = 'blah';sẽ ghi đè lên getItemphương thức của localStorage . jsfiddle.net/DrquY
Fabrício Matté

1
Tôi vẫn chưa thấy một lập luận ủng hộ cách tiếp cận nào giúp tôi chiến thắng. Người ta thực hiện các cặp tên / giá trị như chúng vẫn luôn như vậy. Cái kia cho chúng ta giá trị null khi chúng ta sử dụng phương thức get / set. Tôi cho rằng nếu tôi so sánh với một danh sách các giá trị khác có giá trị rỗng cho các giá trị tùy chọn thì cái này sẽ có ý nghĩa hơn cái kia nhưng nói cái này hay cái kia là 'ưu tiên' khi cả hai đều nằm trong thông số kỹ thuật là ngớ ngẩn, IMO. Cả hai cách tiếp cận đều có sẵn vì một lý do.
Erik Reppen

Câu trả lời:


83

Cả truy cập thuộc tính trực tiếp ( localStorage.itemhoặc localStorage['item']) và sử dụng giao diện chức năng ( localStorage.getItem('item')) đều hoạt động tốt. Cả hai đều là tiêu chuẩn và tương thích với nhiều trình duyệt. * Theo thông số kỹ thuật :

Các tên thuộc tính được hỗ trợ trên đối tượng Lưu trữ là các khóa của mỗi cặp khóa / giá trị hiện có trong danh sách được liên kết với đối tượng, theo thứ tự các khóa được thêm lần cuối vào vùng lưu trữ.

Chúng chỉ hoạt động khác nhau khi không tìm thấy cặp khóa / giá trị nào với tên được yêu cầu. Ví dụ, nếu chìa khóa 'item'không tồn tại, var a = localStorage.item;sẽ cho kết quả aundefined, trong khi var a = localStorage.getItem('item');sẽ dẫn đến acó giá trị null. Như bạn đã phát hiện, undefinednullkhông thể hoán đổi cho nhau trong JavaScript / EcmaScript. :)

CHỈNH SỬA: Như Christoph đã chỉ ra trong câu trả lời của mình , giao diện chức năng là cách duy nhất để lưu trữ và truy xuất các giá trị trong các khóa bằng các thuộc tính được xác định trước một cách đáng tin cậy localStorage. (Có sáu trong số này: length, key, setItem, getItem, removeItem, và clear.) Vì vậy, ví dụ, sau đây sẽ luôn luôn làm việc:

localStorage.setItem('length', 2);
console.log(localStorage.getItem('length'));

Đặc biệt lưu ý rằng câu lệnh đầu tiên sẽ không ảnh hưởng đến thuộc tính localStorage.length(ngoại trừ có thể tăng nó lên nếu chưa có khóa nào 'length'trong đó localStorage). Về mặt này, thông số kỹ thuật dường như không nhất quán.

Tuy nhiên, những điều sau có thể sẽ không làm được những gì bạn muốn:

localStorage.length = 2;
console.log(localStorage.length);

Điều thú vị là đầu tiên là không chọn trong Chrome, nhưng đồng nghĩa với lệnh gọi chức năng trong Firefox. Thứ hai sẽ luôn ghi lại số lượng khóa có trong localStorage.

* Điều này đúng với các trình duyệt hỗ trợ lưu trữ web ngay từ đầu. (Điều này bao gồm hầu hết tất cả các trình duyệt dành cho máy tính để bàn và thiết bị di động hiện đại.) Đối với các môi trường mô phỏng lưu trữ cục bộ bằng cookie hoặc các kỹ thuật khác, hành vi phụ thuộc vào miếng đệm được sử dụng. Một số polyfills cho localStoragecó thể được tìm thấy ở đây .


11

Câu hỏi đã khá cũ, nhưng vì tôi đã được trích dẫn trong câu hỏi, tôi nghĩ tôi nên nói hai từ về tuyên bố của mình.

Đối tượng Lưu trữ khá đặc biệt, nó là một đối tượng, cung cấp quyền truy cập vào danh sách các cặp khóa / giá trị. Vì vậy, nó không phải là một đối tượng hoặc mảng thông thường.

Ví dụ: nó có thuộc tính length, không giống như thuộc tính độ dài mảng là chỉ đọc và trả về số lượng khóa trong bộ nhớ.

Với một mảng bạn có thể làm:

var a = [1,2,3,4];
a.length // => 4
a.length = 2;
a // => [1,2]

Ở đây chúng tôi có lý do đầu tiên để sử dụng getters / setters. Nếu bạn muốn đặt một mục có tên là lengthgì?

localStorage.length = "foo";
localStorage.length  // => 0
localStorage.setItem("length","foo");
// the "length" key is now only accessable via the getter method:
localStorage.length  // => 1
localStorage.getItem("length") // => "foo"

Với các thành viên khác của đối tượng Storage, điều đó thậm chí còn quan trọng hơn, vì chúng có thể ghi được và bạn có thể vô tình ghi đè lên các phương thức như getItem. Sử dụng các phương pháp API ngăn chặn bất kỳ sự cố nào có thể xảy ra và cung cấp Giao diện nhất quán.

Một điểm thú vị nữa là đoạn sau trong thông số (do tôi nhấn mạnh):

Phương thức setItem () và removeItem () phải là nguyên tử đối với sự thất bại. Trong trường hợp thất bại, phương pháp này không làm gì cả. Nghĩa là, các thay đổi đối với vùng lưu trữ dữ liệu phải thành công, hoặc vùng lưu trữ dữ liệu không được thay đổi gì cả.

Về mặt lý thuyết không có sự khác biệt giữa getters / setters và []quyền truy cập, nhưng bạn không bao giờ biết ...


Về điểm đầu tiên, gần như mọi thứ trong JavaScript đều có thể ghi được và API localStorage chỉ có ba thuộc tính mà tôi biết. Thứ hai, sử dụng các phương pháp tiếp cận ký hiệu dấu chấm hoặc dấu ngoặc vuông, bạn vẫn gặp phải một số loại triển khai bộ cài đặt gốc vì các giá trị được tự động chuyển đổi thành chuỗi bất kể bạn đặt chúng như thế nào, vì vậy nó sẽ có sẵn các biện pháp bảo vệ tương tự. Tôi thực sự chưa bao giờ nghe nói về giá trị liên tục bị hỏng trong kịch bản trình duyệt phía máy khách trước đây. Tôi nghi ngờ rằng ngay cả những người truy cập vani thường có một số loại biện pháp bảo vệ.
Erik Reppen

Điểm về va chạm tên là tuyệt vời. Các lengthbất động sản sẽ không thay đổi (ít nhất là trong Chrome và Firefox [*]) nếu bạn gọi localStorage.setItem("length", something);, nhưng bạn có thể lấy somethingvới localStorage.getItem("length");. Điều thú vị là gán localStorage.length = something;trong Chrome là không cần chọn, nhưng trong Firefox, nó sẽ lưu trữ somethingdưới khóa "length"(sau đó bạn chỉ có thể truy xuất bằng giao diện chức năng). [*] Trên thực tế, trong Firefox, thuộc lengthtính sẽ thay đổi nếu bạn "length"chưa có khóa localStorage.
Ted Hopp

@ErikReppen - Theo spec , localStoragecó sáu đặc tính xác định trước: length, key, getItem, setItem, removeItem, và clear.
Ted Hopp

1

Tôi biết đó là một bài đăng cũ nhưng vì không ai thực sự đề cập đến hiệu suất nên tôi đã thiết lập một số bài kiểm tra JsPerf để đánh giá nó và cũng như là một giao diện mạch lạc getItemsetItemcũng nhanh hơn so với sử dụng ký hiệu dấu chấm hoặc dấu ngoặc đơn cũng như dễ đọc hơn nhiều.

Đây là bài kiểm tra của tôi trên JsPerf


jsPerf ur không bao gồm dấu ngoặc trong thử nghiệm của nó. tôi đã thêm chúng và chạy một số thử nghiệm, hiệu suất dựa trên trình duyệt. trên cả chrome và firefox, getItemsetItemlà loại chậm nhất trong mỗi danh mục, với dấu chấm là nhanh nhất trên chrome và dấu ngoặc là nhanh nhất trên firefox. tôi cũng nghĩ rằng 'dễ đọc hơn nhiều' là hoàn toàn chủ quan ... vâng, nó nói rõ chức năng của nó đang hoạt động, nhưng bất kỳ ai đã từng làm việc với biến đối tượng hoặc biến mảng sẽ biết trong nửa giây điều gì đang xảy ra với dấu chấm / dấu ngoặc.
PlantTheIdea

Bạn nói đúng, tại thời điểm viết các bài kiểm tra đó, bộ định tuyến và bộ định tuyến luôn nhanh hơn ký hiệu chấm. Không phải là trường hợp nữa. Khi tôi có 5 phút, tôi sẽ quay lại và cập nhật câu trả lời này. Cảm ơn vì đã chỉ ra điều đó.
Dave Mackintosh

0

Như nó đã được đề cập, hầu như không có sự khác biệt ngoại trừ khóa không tồn tại. Sự khác biệt về hiệu suất thay đổi tùy thuộc vào trình duyệt / hệ điều hành bạn đang sử dụng. Nhưng nó không thực sự khác nhau.

Tôi khuyên bạn nên sử dụng giao diện tiêu chuẩn, chỉ vì đó là cách sử dụng được khuyến nghị.


"Tôi đề nghị bạn sử dụng giao diện tiêu chuẩn" - Cả hai giao diện đều được chỉ định trong tiêu chuẩn.
Ted Hopp

@TedHopp Tôi nghĩ rằng chỉ setItem và getItem được chỉ định trong tiêu chuẩn .
Salvador Dali

2
Ngược lại. Từ tiêu chuẩn: "Tên thuộc tính được hỗ trợ trên đối tượng Lưu trữ là các khóa của mỗi cặp khóa / giá trị hiện có trong danh sách được liên kết với đối tượng, theo thứ tự các khóa được thêm lần cuối vào vùng lưu trữ."
Ted Hopp
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.