read - guardar variable en cookie javascript
¿Cuál es la función más corta para leer una cookie por nombre en JavaScript? (12)
¿Cuál es el método más corto, preciso y compatible con varios navegadores para leer una cookie en JavaScript?
Muy a menudo, al construir scripts independientes (donde no puedo tener ninguna dependencia externa), me encuentro agregando una función para leer cookies, y generalmente recurro al readCookie()
QuirksMode.org readCookie()
(280 bytes, 216). minificado.)
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;
}
Hace el trabajo, pero es feo, y agrega un poco de hinchazón cada vez.
El método que jQuery.cookie usa algo como esto (modificado, 165 bytes, 125 minificado):
function read_cookie(key)
{
var result;
return (result = new RegExp(''(?:^|; )'' + encodeURIComponent(key) + ''=([^;]*)'').exec(document.cookie)) ? (result[1]) : null;
}
Tenga en cuenta que esto no es una competencia ''Code Golf'': estoy legítimamente interesado en reducir el tamaño de mi función readCookie y en garantizar que la solución que tengo sea válida.
Suposiciones
Basado en la pregunta, creo que algunas suposiciones / requisitos para esta función incluyen:
- Se usará como una función de biblioteca y, por lo tanto, se debe incluir en cualquier base de código;
- Como tal, deberá funcionar en muchos entornos diferentes , es decir, trabajar con código JS heredado, CMS de diversos niveles de calidad, etc .;
- Para interoperar con código escrito por otras personas y / o código que usted no controla, la función no debe hacer suposiciones sobre cómo se codifican los nombres o valores de las cookies . Llamar a la función con una cadena
"foo:bar[0]"
debería devolver una cookie (literalmente) llamada "foo: bar [0]"; - Se pueden escribir nuevas cookies y / o modificar las existentes en cualquier momento de la vida de la página.
Bajo estas suposiciones, está claro que encodeURIComponent
/ decodeURIComponent
no debe ser utilizado ; al hacerlo, se supone que el código que estableció la cookie también lo codificó utilizando estas funciones.
El enfoque de expresión regular se vuelve problemático si el nombre de la cookie puede contener caracteres especiales. jQuery.cookie soluciona este problema codificando el nombre de la cookie (en realidad, nombre y valor) al almacenar una cookie y decodificando el nombre al recuperar una cookie. Una solución de expresión regular está debajo.
A menos que solo esté leyendo las cookies que controla completamente, también sería recomendable leer las cookies de document.cookie
directamente y no almacenar en caché los resultados, ya que no hay forma de saber si el caché no es válido sin leer document.cookie
nuevamente.
(Si bien acceder y analizar document.cookies
será un poco más lento que usar un caché, no sería tan lento como leer otras partes del DOM, ya que las cookies no juegan un papel en los árboles DOM / render).
Función basada en bucle
Aquí va la respuesta de Code Golf, basada en la función PPK (basada en bucle):
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, '''');
}
que cuando se minimiza, llega a 128 caracteres (sin contar el nombre de la función):
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,'''');}
Función basada en expresiones regulares
Actualización: si realmente quieres una solución de expresión regular:
function readCookie(name) {
return (name = new RegExp(''(?:^|;//s*)'' + ('''' + name).replace(/[-[/]{}()*+?.,//^$|#/s]/g, ''//$&'') + ''=([^;]*)'').exec(document.cookie)) && name[1];
}
Esto escapes cualquier carácter especial en el nombre de la cookie antes de construir el objeto RegExp. Minificado, esto llega a 134 caracteres (sin contar el nombre de la función):
function readCookie(n){return(n=new RegExp(''(?:^|;//s*)''+(''''+n).replace(/[-[/]{}()*+?.,//^$|#/s]/g,''//$&'')+''=([^;]*)'').exec(document.cookie))&&n[1];}
Como Rudu y los lobos han señalado en los comentarios, la expresión regular que escapa de la expresión se puede acortar por unos pocos caracteres. Creo que sería bueno mantener constante la expresión regular de escape (puede que la estés utilizando en otro lugar), pero vale la pena considerar sus sugerencias.
Notas
Ambas funciones no se manejarán null
o undefined
, es decir, si hay una cookie llamada "null", readCookie(null)
devolverá su valor. Si necesita manejar este caso, adapte el código en consecuencia.
¿Que tal este?
function getCookie(k){var v=document.cookie.match(''(^|;) ?''+k+''=([^;]*)(;|$)'');return v?v[2]:null}
Contó 89 bytes sin el nombre de la función.
(Editar: publicó la versión incorrecta primero ... y una no funcional. Actualizada a la actual, que usa una función de parapaso muy similar al segundo ejemplo).
Buena idea en el primer ejemplo de los lobos. Construí ambos para una función de lectura / escritura de cookies bastante compacta que funciona en múltiples subdominios. Pensé que compartiría en caso de que alguien más se encuentre con este hilo buscando eso.
(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)
- Si pasa rwCookie nada, obtendrá todas las cookies en el almacenamiento de cookies
- Pasó rwCookie un nombre de cookie, obtiene el valor de esa cookie del almacenamiento
- Pasó un valor de cookie, escribe la cookie y coloca el valor en almacenamiento
- El vencimiento está predeterminado en la sesión a menos que especifique uno
Ambas funciones parecen igualmente válidas en términos de lectura de cookies. Sin embargo, puedes ahorrarte algunos bytes (y realmente se está metiendo en el territorio de Code Golf aquí):
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;
}
Todo lo que hice con esto es contraer todas las declaraciones de variables en una sola sentencia var, eliminar los segundos argumentos innecesarios en las llamadas a la subcadena y reemplazar la llamada de una charAt por una deferencia de referencia.
Esto todavía no es tan corto como la segunda función que proporcionó, pero incluso eso puede tener algunos bytes eliminados:
function read_cookie(key)
{
var result;
return (result = new RegExp(''(^|; )'' + encodeURIComponent(key) + ''=([^;]*)'').exec(document.cookie)) ? result[2] : null;
}
Cambié la primera sub-expresión en la expresión regular para que fuera una sub-expresión de captura, y cambié la parte del resultado [1] al resultado [2] para que coincidiera con este cambio; también eliminó los parens innecesarios alrededor del resultado [2].
Aquí está la solución más simple usando las funciones de cadena de javascript.
document.cookie.substring(document.cookie.indexOf("COOKIE_NAME"),
document.cookie.indexOf(";",
document.cookie.indexOf("COOKIE_NAME"))).
substr(COOKIE_NAME.length);
Aquí va ... ¡Salud!
function getCookie(n) {
let a = `; ${document.cookie}`.match(`;//s*${n}=([^;]+)`);
return a ? a[1] : '''';
}
Tenga en cuenta que hice uso de las cadenas de plantillas de ES6 para componer la expresión de expresiones regulares.
Esto solo afectará a document.cookie UNA vez. Cada solicitud posterior será instantánea.
(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
})();
Me temo que realmente no hay una manera más rápida que esta lógica general a menos que seas libre de usar .forEach
que depende del navegador (incluso entonces no estás ahorrando tanto)
Tu propio ejemplo ligeramente comprimido a 120 bytes
:
function read_cookie(k,r){return(r=RegExp(''(^|; )''+encodeURIComponent(k)+''=([^;]*)'').exec(document.cookie))?r[2]:null;}
Puede obtenerlo en 110 bytes
si lo convierte en un nombre de función de 1 letra, 90 bytes
si suelta el encodeURIComponent
.
Lo he reducido a 73 bytes
, pero para ser justos, es 82 bytes
cuando se llama readCookie
y 102 bytes
cuando se agrega encodeURIComponent
:
function C(k){return(document.cookie.match(''(^|; )''+k+''=([^;]*)'')||0)[2]}
Para eliminar realmente tanto hinchazón como sea posible, considere no utilizar una función de envoltura en absoluto:
try {
var myCookie = document.cookie.match(''(^|;) *myCookie=([^;]*)'')[2]
} catch (_) {
// handle missing cookie
}
Siempre que esté familiarizado con RegEx, ese código es razonablemente limpio y fácil de leer.
Usar la respuesta de los lobos, pero no usar un cierre ni un hash precomputado:
// 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];
}
}
... y minificando ...
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];}}
... es igual a 127 bytes.
código 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
}
esto en un objeto que puede leer, escribir, escribir en exceso y eliminar las 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;
}
};
Más corto, más confiable y más eficiente que la respuesta actual mejor votada:
function getCookieValue(a) {
var b = document.cookie.match(''(^|;)//s*'' + a + ''//s*=//s*([^;]+)'');
return b ? b.pop() : '''';
}
Aquí se muestra una comparación de rendimiento de varios enfoques:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Algunas notas sobre el enfoque:
El enfoque de expresiones regulares no solo es el más rápido en la mayoría de los navegadores, también produce la función más corta. Además, debe señalarse que, de acuerdo con la especificación oficial (RFC 2109) , el espacio después del punto y coma que separa las cookies en el documento.cookie es opcional y se podría argumentar que no se debe confiar en él. Además, se permite el espacio en blanco antes y después del signo igual (=) y se podría argumentar que este espacio en blanco potencial debe tenerse en cuenta en cualquier analizador confiable de document.cookie. La expresión regular anterior representa las dos condiciones de espacio en blanco anteriores.