Jaka jest najkrótsza, dokładna i kompatybilna z różnymi przeglądarkami metoda odczytu pliku cookie w JavaScript?
Bardzo często budując samodzielne skrypty (w których nie mogę mieć żadnych zewnętrznych zależności), dodajęreadCookie()
funkcję do czytania plików cookie i zwykle korzystam z metody QuirksMode.org (280 bajtów, 216 min.)
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
Robi robotę, ale jest brzydka i za każdym razem dodaje sporo wzdęci.
Metoda, w której jQuery.cookie używa czegoś takiego (zmodyfikowany, 165 bajtów, 125 minut):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Uwaga: nie jest to konkurs „Code Golf”: jestem prawnie zainteresowany zmniejszeniem wielkości mojej funkcji readCookie i upewnieniem się, że posiadane rozwiązanie jest prawidłowe.
javascript
cookies
Yahel
źródło
źródło
Odpowiedzi:
Krótszy, bardziej niezawodny i skuteczniejszy niż obecnie najlepiej głosowana odpowiedź:
Porównanie wydajności różnych podejść pokazano tutaj:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Kilka uwag na temat podejścia:
Metoda regex jest nie tylko najszybsza w większości przeglądarek, ale także zapewnia najkrótszą funkcję. Ponadto należy zauważyć, że zgodnie z oficjalną specyfikacją (RFC 2109) odstęp po średniku oddzielającym pliki cookie w dokumencie. Plik cookie jest opcjonalny i można argumentować, że nie można się na niego opierać. Dodatkowo spacja jest dozwolona przed i po znaku równości (=) i można argumentować, że ta potencjalna biała spacja powinna być uwzględniona w dowolnym wiarygodnym parserze document.cookie. Wyrażenie regularne powyżej uwzględnia oba powyższe warunki spacji.
źródło
getCookieValue(a, b)
bierze parametrb
?a
ib
robić.a
parametr nie jest poprzedzany znakiem ucieczki, chociaż może być użyteczny, nie jest bezpieczny.getCookieValue('.*')
To tylko raz trafi na document.cookie JEDEN raz. Każde kolejne żądanie będzie natychmiastowe.
Obawiam się, że tak naprawdę nie ma szybszego sposobu niż ta ogólna logika, chyba że możesz swobodnie korzystać z
.forEach
funkcji zależnych od przeglądarki (nawet wtedy nie oszczędzasz zbyt wiele)Twój własny przykład lekko skompresowany do
120 bytes
:Możesz to zrobić,
110 bytes
jeśli uczynisz ją 1-literową nazwą funkcji,90 bytes
jeśli upuściszencodeURIComponent
.Sprowadziłem się do tego
73 bytes
, ale szczerze mówiąc, to82 bytes
kiedy jestem nazwany,readCookie
a102 bytes
kiedy dodajeencodeURIComponent
:źródło
()
na końcu wywołania, więc definiował anonimową funkcję, ale nigdy jej nie wykonywał.Założenia
Na podstawie pytania uważam, że niektóre założenia / wymagania dotyczące tej funkcji obejmują:
"foo:bar[0]"
powinno zwrócić plik cookie (dosłownie) o nazwie „foo: bar [0]”;Zgodnie z tymi założeniami jasne jest, że
encodeURIComponent
/decodeURIComponent
nie należy używać ; Robiąc to, zakłada się, że kod, który ustawia plik cookie, również koduje go przy użyciu tych funkcji.Metoda wyrażeń regularnych staje się problematyczna, jeśli nazwa pliku cookie może zawierać znaki specjalne. jQuery.cookie rozwiązuje ten problem, kodując nazwę pliku cookie (w rzeczywistości zarówno nazwę, jak i wartość) podczas przechowywania pliku cookie oraz dekodując nazwę podczas pobierania pliku cookie.Rozwiązanie wyrażeń regularnych znajduje się poniżej.O ile nie czytasz tylko plików cookie, które kontrolujesz całkowicie, wskazane byłoby również odczytywanie plików cookie
document.cookie
bezpośrednio i nie buforowanie wyników, ponieważ nie ma sposobu, aby dowiedzieć się, czy pamięć podręczna jest nieprawidłowa bezdocument.cookie
ponownego czytania .(Podczas gdy uzyskiwanie dostępu i parsowanie
document.cookies
będzie nieco wolniejsze niż w przypadku użycia pamięci podręcznej, nie będzie tak wolne jak czytanie innych części DOM, ponieważ pliki cookie nie odgrywają roli w drzewach DOM / renderowania).Funkcja oparta na pętli
Oto odpowiedź Code Golf, oparta na funkcji PPK (pętli):
który po zminimalizowaniu ma 128 znaków (nie licząc nazwy funkcji):
Funkcja oparta na wyrażeniach regularnych
Aktualizacja: jeśli naprawdę potrzebujesz rozwiązania wyrażeń regularnych:
Pozwala to uniknąć znaków specjalnych w nazwie pliku cookie przed zbudowaniem obiektu RegExp. Zminimalizowane, zawiera 134 znaki (nie licząc nazwy funkcji):
Jak zauważyli Rudu i cwolves w komentarzach, wyrażenie regularne uciekające od wyrażenia regularnego można skrócić o kilka znaków. Myślę, że dobrze byłoby zachować spójność uciekającego wyrażenia regularnego (być może używasz go gdzie indziej), ale ich sugestie są warte rozważenia.
Notatki
Obie te funkcje nie będą obsługiwać
null
lubundefined
, tj. Jeśli istnieje plik cookie o nazwie „null”,readCookie(null)
zwróci jego wartość. Jeśli musisz poradzić sobie z tą sprawą, odpowiednio dostosuj kod.źródło
#\s
zakończenia wymiany Regex? Tę ogólną zamianę można uprościć jeszcze bardziej (-, nie mają żadnego znaczenia, z wyjątkiem nawiasów, które są/[[\]{}()*+?.\\^$|]/g
encodeURIComponent
/[()*.\\]/g
new RegExp('[' + str + ']')
, to chciałbyś uciec-
), więc prawdopodobnie masz rację, że można go skrócić. Ponieważ pozwoliłoby to zaoszczędzić tylko kilka bajtów, a ucieczka dodatkowych znaków nie wpływa na ostateczną regex, jestem skłonny pozostawić ją taką, jaka jest.encodeURIComponent()
w tym przypadku, ponieważ myślę, że OP szuka ogólnej funkcji, która może działać z dowolną nazwą pliku cookie. Jeśli kod innej firmy ustawi plik cookie o nazwie „foo: bar”, użycieencodeURIComponent()
oznacza próbę odczytania pliku cookie o nazwie „foo% 3Abar”.a<tab>b
wa\<tab>b
... co nie jest prawidłową ucieczką, chociaż\<space>
jest). I # wydaje się nie mieć znaczenia w JS RegExencodeURIComponent
, jeśli plik cookiefoo=
zostałby nazwany , byłby przechowywany, ponieważfoo%3D
bez kodowania nazwy nie można go znaleźć (kod go nie znajdzie) - nie ma właściwej odpowiedzi. Jeśli możesz kontrolować sposób umieszczania plików cookie, możesz uprościć odpowiedź / poczynić założenia, które pomogą je uzyskać. Najprostszym / najlepszym jest użycie tylko a-zA-Z0-9 dla nazwy pliku cookie i unikanie całegoencodeURIComponent
bałaganu ucieczki RegExp. Ale nadal możesz martwićdecodeURIComponent
się wartością pliku cookie, ponieważ jest to zalecana praktyka.kod z google analytics ga.js
źródło
return d[0];
a następnieif (c('EXAMPLE_CK') == null)
sprawdziłem, czy plik cookie nie jest zdefiniowany.Co powiesz na ten?
Zliczono 89 bajtów bez nazwy funkcji.
źródło
k
można nazwaćkey
dla jasności, ale i tak.Proszę bardzo ... Pozdrawiam!
Zauważ, że wykorzystałem ciągi szablonów ES6 do skomponowania wyrażenia regularnego.
źródło
w obiekcie, który można czytać, zapisywać, zastępować i usuwać pliki cookie.
źródło
Obie te funkcje wyglądają równie poprawnie pod względem odczytu plików cookie. Możesz jednak ogolić kilka bajtów (i tak naprawdę dostaje się tutaj na terytorium Code Golf):
Wszystko, co z tym zrobiłem, to zwinięcie wszystkich deklaracji zmiennych w jedną instrukcję var, usunięcie niepotrzebnych drugich argumentów w wywołaniach podłańcuchu i zastąpienie jednego wywołania charAt dereferencją tablicową.
To wciąż nie jest tak krótkie jak druga funkcja, którą podałeś, ale nawet to może mieć kilka bajtów zdjętych:
Zmieniłem pierwsze podwyrażenie w wyrażeniu regularnym na przechwytywanie podwyrażenia i zmieniłem część wynikową [1] na wynikową [2], aby pokrywała się z tą zmianą; usunięto także niepotrzebne skrawki wokół wyniku [2].
źródło
Aby naprawdę usunąć jak najwięcej wzdęć, należy w ogóle nie używać funkcji otoki:
O ile znasz RegEx, kod ten jest dość czysty i łatwy do odczytania.
źródło
(edytuj: najpierw opublikowałem niewłaściwą wersję .. i niefunkcjonalną. Zaktualizowano do bieżącej, która używa funkcji unparam, która jest bardzo podobna do drugiego przykładu).
Fajny pomysł w pierwszym przykładzie cwolves. Zbudowałem oba w celu uzyskania dość zwartej funkcji odczytu / zapisu plików cookie, która działa w wielu subdomenach. Pomyślałem, że podzielę się, na wypadek, gdyby ktoś szukał tego wątku.
źródło
Używając odpowiedzi cwolves, ale nie używając zamknięcia ani wcześniej obliczonego skrótu:
... i minimalizowanie ...
... równa się 127 bajtów.
źródło
Oto najprostsze rozwiązanie z wykorzystaniem funkcji ciągu javascript.
źródło
Poniższa funkcja pozwoli rozróżnić puste ciągi znaków i niezdefiniowane pliki cookie. Niezdefiniowane pliki cookie zostaną poprawnie zwrócone,
undefined
a nie pusty ciąg, w przeciwieństwie do niektórych innych odpowiedzi tutaj. Ale to nie będzie działać na IE7 i niższych, ponieważ nie pozwalają one na dostęp tablicy do indeksów ciągów.źródło