Was ist die kürzeste, genaueste und browserübergreifendste Methode zum Lesen eines Cookies in JavaScript?
Sehr oft fügereadCookie()
ich beim Erstellen von eigenständigen Skripten (bei denen ich keine externen Abhängigkeiten haben kann) eine Funktion zum Lesen von Cookies hinzu und greife normalerweise auf die QuirksMode.org- Methode zurück (280 Byte, 216 minimiert).
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;
}
Es macht den Job, aber es ist hässlich und fügt jedes Mal einiges an Blähungen hinzu.
Die Methode, die jQuery.cookie verwendet , ist ungefähr so (geändert, 165 Byte, 125 minimiert):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Beachten Sie, dass dies kein "Code Golf" -Wettbewerb ist: Ich bin zu Recht daran interessiert, die Größe meiner readCookie-Funktion zu reduzieren und sicherzustellen, dass meine Lösung gültig ist.
javascript
cookies
Yahel
quelle
quelle
Antworten:
Kürzer, zuverlässiger und leistungsfähiger als die derzeit am besten gewählte Antwort:
Ein Leistungsvergleich verschiedener Ansätze wird hier gezeigt:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Einige Hinweise zum Ansatz:
Der Regex-Ansatz ist in den meisten Browsern nicht nur der schnellste, sondern bietet auch die kürzeste Funktion. Darüber hinaus sollte darauf hingewiesen werden, dass gemäß der offiziellen Spezifikation (RFC 2109) das Leerzeichen nach dem Semikolon, das Cookies im document.cookie trennt, optional ist und ein Argument angeführt werden könnte, auf das man sich nicht verlassen sollte. Darüber hinaus ist ein Leerzeichen vor und nach dem Gleichheitszeichen (=) zulässig, und es könnte argumentiert werden, dass dieses potenzielle Leerzeichen in einen zuverlässigen document.cookie-Parser einbezogen werden sollte. Der obige reguläre Ausdruck berücksichtigt beide oben genannten Leerzeichenbedingungen.
quelle
getCookieValue(a, b)
Parameterb
?a
und wasb
ich tun soll.a
Der Parameter ist nicht mit einem regulären Ausdruck versehen, obwohl er nützlich sein kann, aber nicht sicher ist. Dinge wiegetCookieValue('.*')
werden jeden zufälligen Cookie zurückgebenDies wird immer nur EINMAL auf document.cookie treffen. Jede nachfolgende Anfrage erfolgt sofort.
Ich fürchte, es gibt wirklich keinen schnelleren Weg als diese allgemeine Logik, es sei denn, Sie können sie verwenden,
.forEach
die vom Browser abhängig ist (selbst dann sparen Sie nicht so viel).Ihr eigenes Beispiel leicht komprimiert auf
120 bytes
:Sie können es erreichen,
110 bytes
wenn Sie es zu einem 1-Buchstaben-Funktionsnamen machen,90 bytes
wenn Sie das löschenencodeURIComponent
.Ich habe es auf den Punkt gebracht
73 bytes
, aber um fair zu sein,82 bytes
wenn es benannt wirdreadCookie
und102 bytes
dann hinzugefügt wirdencodeURIComponent
:quelle
()
Aufruf am Ende nicht, definierte also eine anonyme Funktion, führte sie jedoch nie aus.Annahmen
Aufgrund der Frage glaube ich, dass einige Annahmen / Anforderungen für diese Funktion Folgendes umfassen:
"foo:bar[0]"
sollte ein Cookie (wörtlich) mit dem Namen "foo: bar [0]" zurückgeben.Unter diesen Annahmen ist klar, dass
encodeURIComponent
/decodeURIComponent
nicht verwendet werden sollte ; Dabei wird davon ausgegangen, dass der Code, der das Cookie gesetzt hat, es auch mit diesen Funktionen codiert hat.Der Ansatz mit regulären Ausdrücken wird problematisch, wenn der Cookie-Name Sonderzeichen enthalten kann. jQuery.cookie umgeht dieses Problem, indem es beim Speichern eines Cookies den Cookie-Namen (eigentlich Name und Wert) codiert und beim Abrufen eines Cookies den Namen decodiert.Eine Lösung für reguläre Ausdrücke finden Sie weiter unten.Wenn Sie nicht nur Cookies lesen, die Sie vollständig kontrollieren, ist es auch ratsam, Cookies
document.cookie
direkt zu lesen und die Ergebnisse nicht zwischenzuspeichern, da es keine Möglichkeit gibt, festzustellen, ob der Cache ohne Lesen ungültig istdocument.cookie
erneut .(Während der Zugriff und das Parsen
document.cookies
etwas langsamer sind als die Verwendung eines Caches, ist er nicht so langsam wie das Lesen anderer Teile des DOM, da Cookies in den DOM- / Render-Bäumen keine Rolle spielen.)Schleifenbasierte Funktion
Hier ist die Antwort von Code Golf, basierend auf der (schleifenbasierten) Funktion von PPK:
was bei Minimierung 128 Zeichen ergibt (ohne den Funktionsnamen):
Funktion auf der Basis regulärer Ausdrücke
Update: Wenn Sie wirklich eine Lösung für reguläre Ausdrücke wünschen:
Dieses entgeht keine Sonderzeichen in den Cookie - Namen , bevor Sie das RegExp - Objekt zu konstruieren. Minimiert sind dies 134 Zeichen (ohne den Funktionsnamen):
Wie Rudu und cwolves in den Kommentaren hervorgehoben haben, kann der reguläre Ausdruck, der dem regulären Ausdruck entgeht, um einige Zeichen verkürzt werden. Ich denke, es wäre gut, den entweichenden regulären Ausdruck konsistent zu halten (Sie können ihn an anderer Stelle verwenden), aber ihre Vorschläge sind eine Überlegung wert.
Anmerkungen
Diese beiden Funktionen werden nicht verarbeitet
null
oder geben den Wert zurückundefined
, wenn ein Cookie mit dem Namen "null" vorhanden istreadCookie(null)
. Wenn Sie diesen Fall behandeln müssen, passen Sie den Code entsprechend an.quelle
#\s
am Ende Ihres Ersatz-Regex? Das generische Ersetzen kann etwas weiter vereinfacht werden (-, hat keine Bedeutung außer in Klammern, die/[[\]{}()*+?.\\^$|]/g
encodeURIComponent
/[()*.\\]/g
new RegExp('[' + str + ']')
, möchten Sie entkommen-
), sodass Sie wahrscheinlich Recht haben, dass es verkürzt werden kann. Da nur wenige Bytes eingespart werden und das Entkommen zusätzlicher Zeichen keinen Einfluss auf die endgültige Regex hat, neige ich dazu, sie so zu belassen, wie sie ist.encodeURIComponent()
in diesem Fall vermeiden , weil ich denke, dass das OP nach einer generischen Funktion sucht, die mit jedem Cookie-Namen funktionieren kann. Wenn der Code eines Drittanbieters ein Cookie mit dem Namen "foo: bar" setzt, bedeutet die VerwendungencodeURIComponent()
, dass versucht wird, ein Cookie mit dem Namen "foo% 3Abar" zu lesen.a<tab>b
ina\<tab>b
... verwandeln, was jedoch keine gültige Flucht\<space>
ist). Und # scheint in JS RegExencodeURIComponent
. Wenn ein Cookie benannt wurde, wirdfoo=
es so gespeichert, als ob Siefoo%3D
den Namen nicht finden würden, ohne ihn ebenfalls zu codieren (Ihr Code findet ihn nicht) - es gibt keine richtige Antwort. Wenn Sie steuern können, wie die Cookies eingefügt werden, können Sie die Antwort vereinfachen / Annahmen treffen, um das Herausholen zu erleichtern. Am einfachsten / besten ist es, nur a-zA-Z0-9 für den Cookie-Namen zu verwenden und zu vermeiden, dass das GanzeencodeURIComponent
und RegExp dem Chaos entkommen. Sie können aber nach wie vor zu befürchten müssendecodeURIComponent
auf Cookie - Wert , da dies eine empfohlene Praxis ist.Code von Google Analytics ga.js.
quelle
return d[0];
und dannif (c('EXAMPLE_CK') == null)
überprüft, ob kein Cookie definiert ist.Wie wäre es mit diesem?
89 Bytes ohne Funktionsnamen gezählt.
quelle
k
könntekey
für Klarheit benannt werden, aber trotzdem.Hier geht .. Prost!
Beachten Sie, dass ich die Vorlagenzeichenfolgen von ES6 verwendet habe, um den Regex-Ausdruck zu erstellen.
quelle
Dies in einem Objekt, das Sie lesen, schreiben, überschreiben und Cookies löschen können.
quelle
Beide Funktionen sehen beim Lesen von Cookies gleichermaßen gültig aus. Sie können sich jedoch ein paar Bytes rasieren (und es betritt hier wirklich das Gebiet von Code Golf):
Alles, was ich damit gemacht habe, ist, alle Variablendeklarationen in einer var-Anweisung zusammenzufassen, die unnötigen zweiten Argumente bei Aufrufen von Teilzeichenfolgen zu entfernen und den einen charAt-Aufruf in eine Array-Dereferenzierung zu ersetzen.
Dies ist immer noch nicht so kurz wie die zweite Funktion, die Sie bereitgestellt haben, aber selbst das kann ein paar Bytes entfernen:
Ich habe den ersten Unterausdruck im regulären Ausdruck in einen erfassenden Unterausdruck geändert und den Teil Ergebnis [1] in Ergebnis [2] geändert, um mit dieser Änderung übereinzustimmen. entfernte auch die unnötigen Parens um das Ergebnis [2].
quelle
Um wirklich so viel Aufblähung wie möglich zu entfernen, sollten Sie keine Wrapper-Funktion verwenden:
Solange Sie mit RegEx vertraut sind, ist dieser Code einigermaßen sauber und leicht zu lesen.
quelle
(Bearbeiten: zuerst die falsche Version gepostet .. und eine nicht funktionierende. Aktualisiert auf den aktuellen Stand, der eine unparam-Funktion verwendet, die dem zweiten Beispiel sehr ähnlich ist.)
Gute Idee im ersten Beispiel cwolves. Ich habe auf beiden aufgebaut, um eine ziemlich kompakte Lese- / Schreibfunktion für Cookies zu erhalten, die über mehrere Subdomänen hinweg funktioniert. Ich dachte, ich würde es teilen, falls jemand anderes auf diesen Thread stößt und danach sucht.
quelle
Verwenden Sie die Antwort von cwolves, aber weder einen Abschluss noch einen vorberechneten Hash:
... und minimieren ...
... entspricht 127 Bytes.
quelle
Hier ist die einfachste Lösung mit Javascript-Zeichenfolgenfunktionen.
quelle
Die folgende Funktion ermöglicht die Unterscheidung zwischen leeren Zeichenfolgen und undefinierten Cookies. Undefinierte Cookies werden korrekt zurückgegeben
undefined
und im Gegensatz zu einigen anderen Antworten hier keine leere Zeichenfolge. Unter IE7 und darunter funktioniert dies jedoch nicht, da sie keinen Array-Zugriff auf Zeichenfolgenindizes ermöglichen.quelle