Quelle est la méthode la plus courte, précise et compatible avec tous les navigateurs pour lire un cookie en JavaScript?
Très souvent, lors de la création de scripts autonomes (où je ne peux pas avoir de dépendances extérieures), je me retrouve à ajouter une fonction de lecture des cookies, et généralement à recourir à lareadCookie()
méthode QuirksMode.org (280 octets, 216 minifiés.)
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;
}
Il fait le travail, mais c'est moche, et ajoute un peu de ballonnement à chaque fois.
La méthode que jQuery.cookie utilise quelque chose comme ça (modifié, 165 octets, 125 minifié):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Notez que ce n'est pas une compétition de «Code Golf»: je suis légitimement intéressé à réduire la taille de ma fonction readCookie et à m'assurer que la solution que j'ai est valide.
la source
Réponses:
Plus courte, plus fiable et plus performante que la réponse la mieux votée actuelle:
function getCookieValue(a) { var b = document.cookie.match('(^|;)\\s*' + a + '\\s*=\\s*([^;]+)'); return b ? b.pop() : ''; }
Une comparaison des performances de diverses approches est présentée ici:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Quelques notes d'approche:
L'approche regex n'est pas seulement la plus rapide dans la plupart des navigateurs, elle offre également la fonction la plus courte. De plus, il convient de souligner que selon la spécification officielle (RFC 2109) , l'espace après le point-virgule qui sépare les cookies dans le document.cookie est facultatif et un argument pourrait être fait qu'il ne devrait pas être invoqué. De plus, les espaces blancs sont autorisés avant et après le signe égal (=) et un argument pourrait être fait que cet espace blanc potentiel devrait être pris en compte dans tout analyseur document.cookie fiable. Le regex ci-dessus tient compte des deux conditions d'espaces ci-dessus.
la source
getCookieValue(a, b)
le paramètreb
?a
etb
faire.a
Le paramètre n'est pas échappé à l'expression régulière, alors qu'il peut être utile, il n'est pas sûr. Des choses commegetCookieValue('.*')
Cela n'atteindra document.cookie qu'une seule fois. Chaque demande ultérieure sera instantanée.
(function(){ var cookies; function readCookie(name,c,C,i){ if(cookies){ return cookies[name]; } c = document.cookie.split('; '); cookies = {}; for(i=c.length-1; i>=0; i--){ C = c[i].split('='); cookies[C[0]] = C[1]; } return cookies[name]; } window.readCookie = readCookie; // or expose it however you want })();
J'ai peur qu'il n'y ait vraiment de moyen plus rapide que cette logique générale à moins que vous ne soyez libre d'utiliser
.forEach
ce qui dépend du navigateur (même dans ce cas, vous n'économisez pas beaucoup)Votre propre exemple légèrement compressé en
120 bytes
:function read_cookie(k,r){return(r=RegExp('(^|; )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
Vous pouvez l'obtenir
110 bytes
si vous en faites un nom de fonction d'une lettre,90 bytes
si vous supprimez le fichierencodeURIComponent
.Je l'ai compris
73 bytes
, mais pour être honnête, il est82 bytes
nomméreadCookie
et102 bytes
ajoutéencodeURIComponent
:function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]}
la source
()
appel à la fin, donc il définissait une fonction anonyme mais ne l'exécutait jamais.Hypothèses
Sur la base de la question, je pense que certaines hypothèses / exigences pour cette fonction comprennent:
"foo:bar[0]"
doit renvoyer un cookie (littéralement) nommé "foo: bar [0]";Sous ces hypothèses, il est clair que
encodeURIComponent
/decodeURIComponent
ne doit pas être utilisé ; cela suppose que le code qui a défini le cookie l'a également codé à l'aide de ces fonctions.L'approche par expression régulière pose problème si le nom du cookie peut contenir des caractères spéciaux. jQuery.cookie contourne ce problème en codant le nom du cookie (en fait à la fois le nom et la valeur) lors du stockage d'un cookie et en décodant le nom lors de la récupération d'un cookie.Une solution d'expression régulière est ci-dessous.À moins que vous ne lisiez que les cookies que vous contrôlez complètement, il serait également conseillé de lire
document.cookie
directement les cookies et de ne pas mettre en cache les résultats, car il n'y a aucun moyen de savoir si le cache est invalide sans le reliredocument.cookie
.(Bien que l'accès et l'analyse
document.cookies
soient légèrement plus lents que l'utilisation d'un cache, ce ne serait pas aussi lent que la lecture d'autres parties du DOM, car les cookies ne jouent pas de rôle dans les arbres DOM / rendu.)Fonction basée sur la boucle
Voici la réponse Code Golf, basée sur la fonction PPK (basée sur la boucle):
function readCookie(name) { name += '='; for (var ca = document.cookie.split(/;\s*/), i = ca.length - 1; i >= 0; i--) if (!ca[i].indexOf(name)) return ca[i].replace(name, ''); }
qui une fois minifié, arrive à 128 caractères (sans compter le nom de la fonction):
function readCookie(n){n+='=';for(var a=document.cookie.split(/;\s*/),i=a.length-1;i>=0;i--)if(!a[i].indexOf(n))return a[i].replace(n,'');}
Fonction basée sur des expressions régulières
Mise à jour: si vous voulez vraiment une solution d'expression régulière:
function readCookie(name) { return (name = new RegExp('(?:^|;\\s*)' + ('' + name).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '=([^;]*)').exec(document.cookie)) && name[1]; }
Cela échappe tous les caractères spéciaux dans le nom du cookie avant de construire l'objet RegExp. Minifié, cela revient à 134 caractères (sans compter le nom de la fonction):
function readCookie(n){return(n=new RegExp('(?:^|;\\s*)'+(''+n).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,'\\$&')+'=([^;]*)').exec(document.cookie))&&n[1];}
Comme Rudu et cwolves l'ont souligné dans les commentaires, l'expression régulière d'échappement d'expressions régulières peut être raccourcie de quelques caractères. Je pense que ce serait bien de garder la règle d'échappement cohérente (vous l'utilisez peut-être ailleurs), mais leurs suggestions valent la peine d'être prises en compte.
Remarques
Ces deux fonctions ne gèrent pas
null
ouundefined
, c'est-à-dire s'il y a un cookie nommé "null",readCookie(null)
renverront sa valeur. Si vous devez gérer ce cas, adaptez le code en conséquence.la source
#\s
fin de votre replace-Regex? Ce remplacement générique peut être simplifié un peu plus (-, n'a pas de sens sauf entre parenthèses qui sont échappées):/[[\]{}()*+?.\\^$|]/g
Il peut être encore plus trieur avecencodeURIComponent
:/[()*.\\]/g
new RegExp('[' + str + ']')
vous voudriez vous échapper-
), vous avez donc probablement raison de le raccourcir. Comme il ne sauverait que quelques octets et que l'échappement de caractères supplémentaires n'affecterait pas l'expression régulière finale, je suis enclin à le laisser tel quel.encodeURIComponent()
dans ce cas parce que je pense que l'OP recherche une fonction générique qui peut fonctionner avec n'importe quel nom de cookie. Si un code tiers définit un cookie nommé "foo: bar", utiliserencodeURIComponent()
signifiera essayer de lire un cookie nommé "foo% 3Abar".a<tab>b
ena\<tab>b
... ce qui n'est pas une évasion valable, bien que ce\<space>
soit). Et # semble n'avoir aucune signification dans JS RegExencodeURIComponent
, si un cookie était nommé,foo=
il serait stocké carfoo%3D
sans encoder le nom de la même manière, vous ne le trouverez pas (votre code ne le trouvera pas) - il n'y a pas de bonne réponse. Si vous pouvez contrôler la façon dont les cookies sont placés, vous pouvez simplifier la réponse / faire des hypothèses pour aider à les sortir. Le plus simple / le meilleur est d'utiliser uniquement a-zA-Z0-9 pour le nom du cookie et d'éviter que leencodeURIComponent
désordre entier et RegExp ne s'échappe. Mais vous pouvez toujours besoin de vous soucierdecodeURIComponent
de la valeur du cookie puisque c'est une pratique recommandée.code de google analytics ga.js
function c(a){ var d=[], e=document.cookie.split(";"); a=RegExp("^\\s*"+a+"=\\s*(.*?)\\s*$"); for(var b=0;b<e.length;b++){ var f=e[b].match(a); f&&d.push(f[1]) } return d }
la source
return d[0];
et ensuite jeif (c('EXAMPLE_CK') == null)
vérifiais si le cookie n'est pas défini.Celui-ci, ça va?
function getCookie(k){var v=document.cookie.match('(^|;) ?'+k+'=([^;]*)(;|$)');return v?v[2]:null}
Compté 89 octets sans le nom de la fonction.
la source
k
pourrait être nommékey
pour la clarté, mais de toute façon.Ici va .. Cheers!
function getCookie(n) { let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`); return a ? a[1] : ''; }
Notez que j'ai utilisé les chaînes de modèle d'ES6 pour composer l'expression regex.
la source
ceci dans un objet que vous pouvez lire, écrire, écraser et supprimer les cookies.
var cookie = { write : function (cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = "expires="+d.toUTCString(); document.cookie = cname + "=" + cvalue + "; " + expires; }, read : function (name) { if (document.cookie.indexOf(name) > -1) { return document.cookie.split(name)[1].split("; ")[0].substr(1) } else { return ""; } }, delete : function (cname) { var d = new Date(); d.setTime(d.getTime() - 1000); var expires = "expires="+d.toUTCString(); document.cookie = cname + "=; " + expires; } };
la source
Ces deux fonctions semblent également valables en termes de lecture des cookies. Vous pouvez cependant raser quelques octets (et cela entre vraiment dans le territoire de Code Golf ici):
function readCookie(name) { var nameEQ = name + "=", ca = document.cookie.split(';'), i = 0, c; for(;i < ca.length;i++) { c = ca[i]; while (c[0]==' ') c = c.substring(1); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length); } return null; }
Tout ce que j'ai fait avec cela est de réduire toutes les déclarations de variables en une seule instruction var, de supprimer les deuxièmes arguments inutiles dans les appels à substring et de remplacer l'appel unique charAt dans un déréférencement de tableau.
Ce n'est toujours pas aussi court que la deuxième fonction que vous avez fournie, mais même cela peut avoir quelques octets supprimés:
function read_cookie(key) { var result; return (result = new RegExp('(^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? result[2] : null; }
J'ai changé la première sous-expression de l'expression régulière en une sous-expression de capture, et j'ai changé la partie résultat [1] en résultat [2] pour coïncider avec ce changement; également supprimé les parenthèses inutiles autour du résultat [2].
la source
Pour vraiment supprimer autant de ballonnements que possible, envisagez de ne pas utiliser du tout de fonction wrapper:
try { var myCookie = document.cookie.match('(^|;) *myCookie=([^;]*)')[2] } catch (_) { // handle missing cookie }
Tant que vous êtes familier avec RegEx, ce code est raisonnablement propre et facile à lire.
la source
Pour que tous les cookies soient accessibles par nom dans une carte :
const cookies = "a=b ; c = d ;e="; const map = cookies.split(";").map((s) => s.split("=").map((s) => s.trim())).reduce((m, [k, v]) => (m.set(k, v), m), new Map()); console.log(map); //Map(3) {'a' => 'b', 'c' => 'd', 'e' => ''} map.get("a"); //returns "b" map.get("c"); //returns "d" map.get("e"); //returns ""
la source
La fonction suivante permettra de différencier les chaînes vides et les cookies non définis. Les cookies non définis seront correctement renvoyés
undefined
et non une chaîne vide contrairement à certaines des autres réponses ici.function getCookie(name) { return (document.cookie.match('(^|;) *'+name+'=([^;]*)')||[])[1]; }
Ce qui précède a bien fonctionné pour moi sur tous les navigateurs que j'ai vérifiés, mais comme mentionné par @vanovm dans les commentaires, selon la spécification, la clé / valeur peut être entourée d'espaces blancs. Par conséquent, ce qui suit est plus conforme aux normes.
function getCookie(name) { return (document.cookie.match('(?:^|;)\\s*'+name.trim()+'\\s*=\\s*([^;]*?)\\s*(?:;|$)')||[])[1]; }
la source
=
sont acceptables mais facultatifs (notez que ce sont des espaces, pas seulement des espaces)(modifier: a d'abord publié la mauvaise version .. et une non fonctionnelle à cela. Mis à jour à la version actuelle, qui utilise une fonction unparam qui ressemble beaucoup au deuxième exemple.)
Belle idée dans le premier exemple cwolves. J'ai construit sur les deux pour une fonction de lecture / écriture de cookies assez compacte qui fonctionne sur plusieurs sous-domaines. Je pensais que je partagerais au cas où quelqu'un d'autre rencontrerait ce fil à la recherche de cela.
(function(s){ s.strToObj = function (x,splitter) { for ( var y = {},p,a = x.split (splitter),L = a.length;L;) { p = a[ --L].split ('='); y[p[0]] = p[1] } return y }; s.rwCookie = function (n,v,e) { var d=document, c= s.cookies||s.strToObj(d.cookie,'; '), h=location.hostname, domain; if(v){ domain = h.slice(h.lastIndexOf('.',(h.lastIndexOf('.')-1))+1); d.cookie = n + '=' + (c[n]=v) + (e ? '; expires=' + e : '') + '; domain=.' + domain + '; path=/' } return c[n]||c }; })(some_global_namespace)
la source
En utilisant la réponse de cwolves, mais sans utiliser de fermeture ni de hachage pré-calculé:
// Golfed it a bit, too... function readCookie(n){ var c = document.cookie.split('; '), i = c.length, C; for(; i>0; i--){ C = c[i].split('='); if(C[0] == n) return C[1]; } }
... et minifier ...
function readCookie(n){var c=document.cookie.split('; '),i=c.length,C;for(;i>0;i--){C=c[i].split('=');if(C[0]==n)return C[1];}}
... équivaut à 127 octets.
la source
Voici la solution la plus simple utilisant des fonctions de chaîne javascript.
document.cookie.substring(document.cookie.indexOf("COOKIE_NAME"), document.cookie.indexOf(";", document.cookie.indexOf("COOKIE_NAME"))). substr(COOKIE_NAME.length);
la source
COOKIE_NAME
une chaîne ou une variable? Votre exemple n'a pas de sens ...Juste pour jeter mon chapeau dans la course, voici ma proposition:
function getCookie(name) { const cookieDict = document.cookie.split(';') .map((x)=>x.split('=')) .reduce((accum,current) => { accum[current[0]]=current[1]; return accum;}, Object()); return cookieDict[name]; }
Le code ci-dessus génère un dict qui stocke les cookies sous forme de paires clé-valeur (c'est-à-dire
cookieDict
), et accède ensuite à la propriéténame
pour récupérer le cookie.Cela pourrait effectivement être exprimé comme un one-liner, mais ce n'est que pour les courageux:
document.cookie.split(';').map((x)=>x.split('=')).reduce((accum,current) => { accum[current[0]]=current[1]; return accum;}, {})[name]
La meilleure approche absolue serait de générer
cookieDict
au chargement de la page, puis tout au long du cycle de vie de la page, d'accéder simplement aux cookies individuels en appelantcookieDict['cookiename']
.la source