Quelle est la méthode la plus courte, précise et compatible avec plusieurs navigateurs pour lire un cookie en JavaScript?
Très souvent, lors de la construction de scripts autonomes (où je ne peux pas avoir de dépendances extérieures), je me trouve ajouter une fonction pour lire les cookies, et généralement me rabattre sur le QuirksMode.org readCookie()
méthode (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 gonflement à chaque fois.
La méthode qui jQuery.cookie utilise quelque chose comme ceci (modifié, 165 octets, 125 minifiées):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Remarque il ne s'agit pas d'un concours "Code Golf": je suis légitimement intéressé par la réduction de la taille de ma fonction readCookie et par la garantie de ma solution. est valable.
Plus court, plus fiable et plus performant que la réponse actuellement la mieux votée:
function getCookieValue(a) {
var b = document.cookie.match('(^|[^;]+)\\s*' + a + '\\s*=\\s*([^;]+)');
return b ? b.pop() : '';
}
(Edit: '(^|;)\\s*'
=> '(^|[^;]+)\\s*'
, ne fonctionnait auparavant que pour le premier cookie)
Une comparaison des performances de différentes approches est montrée ici:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Quelques notes sur l'approche:
L’approche regex n’est pas seulement la plus rapide dans la plupart des navigateurs, elle fournit également la fonction la plus courte. De plus, il convient de noter que, conformément à 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 qu'il est possible de faire valoir qu'il ne devrait pas être invoqué. En outre, les espaces sont autorisés avant et après le signe égal (=) et un argument peut être avancé pour que ces espaces potentiels soient pris en compte dans tout analyseur document.cookie fiable. L'expression rationnelle ci-dessus représente les deux conditions d'espaces ci-dessus.
Cela ne fera que frapper document.cookie 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 bien peur qu'il n'y ait pas vraiment de moyen plus rapide que cette logique générale à moins que vous ne soyez libre d'utiliser .forEach
qui dépend du navigateur (même dans ce cas, vous n'enregistrez pas beaucoup)
Votre propre exemple légèrement compressé à 120 bytes
:
function read_cookie(k,r){return(r=RegExp('(^|; )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
Vous pouvez l'obtenir dans 110 bytes
si vous lui attribuez un nom de fonction à une lettre, 90 bytes
si vous supprimez la encodeURIComponent
.
Je l'ai descendu à 73 bytes
, mais pour être juste, c'est 82 bytes
lorsqu'il est nommé readCookie
et 102 bytes
lorsque l'on ajoute ensuite encodeURIComponent
:
function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]}
Sur la base de la question, je pense que certaines hypothèses/exigences pour cette fonction incluent:
"foo:bar[0]"
devrait 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 des expressions régulières devient problématique si le nom du cookie peut contenir des caractères spéciaux. jQuery.cookie contourne ce problème en encodant le nom du cookie (en réalité, le nom et la valeur) lors du stockage d'un cookie et en le décodant 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 les cookies de document.cookie
directement et ne pas mettre en cache les résultats, puisqu'il n'y a aucun moyen de savoir si le cache est invalide sans relire document.cookie
.
(Tout en accédant et en analysant document.cookies
sera un peu plus lent que d'utiliser un cache, ce ne serait pas aussi lent que de lire d'autres parties du DOM, car les cookies ne jouent pas de rôle dans les arborescences DOM/rendu.)
Voici la réponse Code Golf, basée sur la fonction de 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és, passe à 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,'');}
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];
}
Ceci échappe tous les caractères spéciaux dans le nom du cookie avant de construire l'objet RegExp. Minified, cela passe à 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 les loups l'ont souligné dans les commentaires, l'expression rationnelle qui évite les expressions régulières peut être raccourcie de quelques caractères. Je pense qu'il serait bon de garder la regex qui s'échappe cohérente (vous l'utilisez peut-être ailleurs), mais leurs suggestions méritent d'être prises en compte.
Ces deux fonctions ne gèrent pas null
ou undefined
, c'est-à-dire que s'il existe un cookie nommé "null", readCookie(null)
renverra sa valeur. Si vous devez gérer ce cas, adaptez le code en conséquence.
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
}
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.
Ici va .. À la votre!
function getCookie(n) {
let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`);
return a ? a[1] : '';
}
Notez que j'ai utilisé les modèles de chaîne de caractères d'ES6 pour composer l'expression regex.
ceci dans un objet que vous pouvez lire, écrire, écraser et supprimer des 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;
}
};
Ces deux fonctions semblent également valables en termes de lecture de cookie. Vous pouvez cependant gagner quelques octets (et vous entrez ici dans le territoire de Code Golf):
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 variable en une seule instruction var, de supprimer les seconds arguments inutiles dans les appels à la sous-chaîne et de remplacer l'appel à 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 modifié la première sous-expression de l'expression régulière pour qu'elle devienne une sous-expression de capture, puis j'ai modifié la partie résultat [1] en résultat [2] afin qu'elle coïncide avec ce changement; a également supprimé les parenthèses inutiles autour du résultat [2].
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);
(edit: posté la mauvaise version en premier .. et une version non fonctionnelle. Mise à jour vers la version actuelle, qui utilise une fonction unparam qui ressemble beaucoup au deuxième exemple.)
Belle idée dans le premier exemple des loups. Je me suis appuyé sur les deux pour créer une fonction de lecture/écriture de cookie assez compacte qui fonctionne sur plusieurs sous-domaines. Je pensais que je partagerais au cas où quelqu'un d'autre parcourrait 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)
Utiliser la réponse de cwolves, mais pas avec une fermeture ni un 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 minifiant ...
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 fonction suivante permettra de différencier les chaînes vides des cookies non définis. Les cookies non définis renverront correctement undefined
et non une chaîne vide contrairement à certaines des autres réponses fournies ici. Mais cela ne fonctionnera pas sur IE7 et les versions antérieures, car elles n'autorisent pas l'accès par tableau aux index de chaînes.
function getCookie(name) {
return (document.cookie.match('(^|;) *'+name+'=([^;]*)')||"")[2];
}
Pour vraiment supprimer autant que possible le gonflement, envisagez de ne pas utiliser de fonction wrapper:
try {
var myCookie = document.cookie.match('(^|;) *myCookie=([^;]*)')[2]
} catch (_) {
// handle missing cookie
}
Tant que vous connaissez RegEx, ce code est relativement propre et facile à lire.