Czy istnieje ograniczenie długości klucza (ciągu znaków) w obiekcie JS?

85

Mieliśmy więc przypadek, w którym mielibyśmy obiekt, w którym klucz to id (int), a wartość to łańcuch. Ale zauważyliśmy, że w większości przypadków wyszukujemy id na podstawie łańcucha, więc zdecydowaliśmy się go odwrócić i uczynić ciąg kluczem, a wartością jest id. Ponieważ w ten sposób zamiast przechodzić przez każdy element i porównywać wartości, moglibyśmy po prostu zrobić var id = storage[text];. Poniżej znajdują się przykłady tego, co zrobiliśmy.

Oto przykład starej implementacji:

var storage = {
  0 : null,
  1 : "Hello",
  2 : "world!",
  3 : "How are you?"
}

Oto przykład nowej implementacji:

var storage = {
  "null" : 0,
  "Hello" : 1,
  "world!" : 2,
  "How are you?" : 3
}

Rozumiem, że teraz ciąg jest kluczem i można uzyskać ten sam identyfikator dla tych samych ciągów. Ale od teraz ciąg może być potencjalnie dość duży (niewielkie szanse, ale prawdopodobnie maksymalnie 1 KB na ciąg), czy istnieje ograniczenie długości, które JS lub Android Webview nakłada na klucze obiektów?

A także, czy ta implementacja ma wady? Jak dotąd nie zauważyłem żadnych problemów, ale nigdy nie wiadomo.

Sherzod
źródło

Odpowiedzi:

98

Trochę to zbadałem.

MDN milczy na ten temat, podobnie jak specyfikacja ( ES5 , ES6 ). Stwierdzają jedynie, że akcesor właściwości musi być ciągiem znaków, bez żadnych zastrzeżeń - innymi słowy, nie ma ograniczeń, jeśli chodzi o specyfikację. Trudno się temu dziwić.

Jak przeglądarki sobie z tym radzą, to inna sprawa. Skonfigurowałem test i uruchomiłem go w wielu przeglądarkach. Chrome 40 (komputer stacjonarny), Chrome 40 (Android 5.1), Firefox 36, Opera 27 i IE9 + mogą obsługiwać nazwę właściwości składającą się z maksymalnie 2 27 znaków. Safari 8 (OS X Yosemite) może nawet obsługiwać nazwy właściwości składające się z 2 30 znaków.

We wszystkich przeglądarkach z wyjątkiem IE maksymalna długość właściwości jest taka sama, jak maksymalna długość ciągu. IE9 + może obsłużyć maksymalną długość ciągu ~ 2 30 znaków, ale limit kluczy obiektów wynosi 2 27 znaków, tak jak w innych przeglądarkach.

Test nie zadziałał w IE8 i Safari na iOS, prawdopodobnie z powodu problemów z pamięcią spowodowanych przez kod testowy.

Krótko mówiąc, używanie długich nazw właściwości jest bezpieczne, nawet jeśli idzie o skrajności. Dopóki same łańcuchy nie przekraczają granic obsługiwanych przez przeglądarki, możesz ich również używać jako nazw właściwości.

hashchange
źródło
18
Wszelkie Runtime kara dla długich kluczy na nowoczesnych przeglądarek?
Ahmed Fasih
@AhmedFasih Nie testowałem tego, więc nie wiem na pewno. Zakładam, że jeśli wystąpi spadek wydajności, będzie to miało związek z porównaniem długich ciągów. Zdziwiłbym się, gdyby były kwestie, które mają znaczenie w praktyce - chyba że klucze są ogromne i liczne i zaczniesz uderzać w ograniczenia pamięci, np. Na telefonie komórkowym.
hashchange
7
Specyfikacja ES7 określa limit 2 ^ 53 - 1 "elementów" . Ale myślę, że ogranicza go maksymalny rozmiar sterty
memy
6
MDN milczy w tej sprawie… ”. Już nie . ;-)
RobG
3
Rzeczywiste rozmiary to 2 ^ 27 = 0,125 GB i 2 ^ 30 = 1 GB. To dla mnie dużo :)
Sorin C
34

Nie, nie ma ograniczeń co do długości łańcucha (o ile mieści się w pamięci), a twoja implementacja też wydaje się w porządku. Bardzo często zdarza się, że te tablice „odwrócone” zawierają np. Wartości logiczne. A jeśli chodzi o łańcuchy jako klucze: Łańcuchy są niezmiennymi symbolami, które są przechowywane pod określonym adresem, a to, co faktycznie jest używane jako indeks tablicy, to ten adres (znany również jako wskaźnik lub odwołanie), a nie sam łańcuch.

Ridcully
źródło
7
„Struny są niezmiennymi symbolami”: Gdzie się tego nauczyłeś?
Andrew
4
Ciekawy. Czy możesz dodać odniesienie lub źródło?
zmiana hash
8
W wielu językach ciągi znaków są niezmienne. Javascript jest jednym z tych języków. developer.mozilla.org/en-US/docs/Web/JavaScript/…
hartz89
3
tylko po to, by dodać trochę jasności innym. oznacza to, że nie możesz wykonać akcji, która zmienia ciąg. możesz manipulować i zwrócić nowy ciąg, ale nigdy go nie zmieniaj
Patrick
Przyjęta odpowiedź jest bardziej praktyczna, ale to jest prawdziwa odpowiedź.
theUtherSide
6

Wygląda na to, że w przypadku ECMAScript 2016 istnieje teraz ostateczna odpowiedź na to pytanie. Według MDN Web Docs na string.length :

ECMAScript 2016 (red. 7) ustalił maksymalną długość 2 ^ 53 - 1 elementów. Wcześniej nie określono maksymalnej długości.

Można to również znaleźć w specyfikacji języka ECMAScript® 2016 :

Typ łańcuch jest zbiorem wszystkich uporządkowanych sekwencji zero lub więcej 16-bitowych liczb całkowitych bez znaku ( „elementy”), aż do maksymalnej długości 2 53 -1 elementów.

Franciszek Bartkowiak
źródło