¿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 crear scripts independientes (donde no puedo tener dependencias externas), me encuentro agregando una función para leer cookies, y generalmente recurro alreadCookie()
método QuirksMode.org (280 bytes, 216 minificados).
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 bastante hinchazón cada vez.
El método por el cual jQuery.cookie usa algo como esto (modificado, 165 bytes, 125 minificados):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Tenga en cuenta que esta no es una competencia de 'Código 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.
javascript
cookies
Yahel
fuente
fuente
Respuestas:
Más corto, más confiable y más eficaz que la respuesta actual mejor votada:
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 regex no solo es el más rápido en la mayoría de los navegadores, sino que también ofrece 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 incluirse en cualquier analizador confiable de documentos. La expresión regular anterior representa las dos condiciones de espacio en blanco anteriores.
fuente
getCookieValue(a, b)
toma el parámetrob
?a
yb
hacer.a
El parámetro no se regex escapó, aunque puede ser útil, no es seguro. Cosas comogetCookieValue('.*')
devolverá cualquier cookie aleatoriaEsto solo llegará a document.cookie UNA vez. Cada solicitud posterior será instantánea.
Me temo que no hay una forma más rápida que esta lógica general a menos que sea libre de usar
.forEach
que depende del navegador (incluso entonces no está ahorrando demasiado)Su propio ejemplo ligeramente comprimido para
120 bytes
:Puede obtenerlo
110 bytes
si lo convierte en un nombre de función de 1 letra,90 bytes
si suelta elencodeURIComponent
.Lo he entendido
73 bytes
, pero para ser justos, es82 bytes
cuando se nombrareadCookie
y102 bytes
luego agregaencodeURIComponent
:fuente
()
llamada al final, por lo que estaba definiendo una función anónima pero nunca ejecutándola.Supuestos
Basado en la pregunta, creo que algunos supuestos / requisitos para esta función incluyen:
"foo:bar[0]"
debería devolver una cookie (literalmente) llamada "foo: bar [0]";Bajo estos supuestos, está claro que
encodeURIComponent
/decodeURIComponent
no debe usarse ; Al hacerlo, se supone que el código que establece la cookie también la codificó mediante 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 al codificar el nombre de la cookie (en realidad, tanto el nombre como el valor) al almacenar una cookie y decodificar 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 por completo, también sería recomendable leer las cookies
document.cookie
directamente y no almacenar en caché los resultados, ya que no hay forma de saber si la memoria caché no es válida sindocument.cookie
volver a leer .(Si bien el acceso y el análisis
document.cookies
serán un poco más lentos que el uso de 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):
que cuando se minimiza, llega a 128 caracteres (sin contar el nombre de la función):
Función basada en expresiones regulares
Actualización: si realmente quieres una solución de expresión regular:
Esto escapa a 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):
Como Rudu y cwolves han señalado en los comentarios, la expresión regular de escape de expresión regular se puede acortar con algunos caracteres. Creo que sería bueno mantener la expresión regular de escape consistente (puede estar usándola en otro lugar), pero vale la pena considerar sus sugerencias.
Notas
Ambas funciones no manejarán
null
oundefined
, es decir, si hay una cookie llamada "nulo",readCookie(null)
devolverá su valor. Si necesita manejar este caso, adapte el código en consecuencia.fuente
#\s
al final de su reemplazo-Regex? Ese reemplazo genérico se puede simplificar un poco más (-, no tiene sentido excepto entre paréntesis que se escapan):/[[\]{}()*+?.\\^$|]/g
incluso se puede clasificar conencodeURIComponent
:/[()*.\\]/g
new RegExp('[' + str + ']')
entonces querría escapar-
), por lo que probablemente tenga razón en que puede acortarse. Como solo ahorraría unos pocos bytes, y escapar caracteres adicionales no afecta la expresión regular final, me inclino a dejarlo como está.encodeURIComponent()
en este caso porque creo que el OP está buscando una función genérica que pueda funcionar con cualquier nombre de cookie. Si el código de terceros establece una cookie llamada "foo: bar", usarencodeURIComponent()
significará intentar leer una cookie llamada "foo% 3Abar".a<tab>b
ena\<tab>b
... lo cual, aunque no es un escape válido\<space>
). Y # parece no tener sentido en JS RegExencodeURIComponent
, si se nombra una cookiefoo=
, se almacenaría como sifoo%3D
no codificara el nombre de la misma manera que no lo encontrará (su código no lo encontrará): no hay una respuesta correcta. Si puede controlar cómo se colocan las cookies, puede simplificar la respuesta / hacer suposiciones para ayudar a sacarla. Lo más simple / mejor es usar solo a-zA-Z0-9 para el nombre de la cookie y evitar todo elencodeURIComponent
desastre de escape de RegExp. Pero es posible que deba preocuparse pordecodeURIComponent
el valor de las cookies, ya que es una práctica recomendada.código de google analytics ga.js
fuente
return d[0];
y luego solíaif (c('EXAMPLE_CK') == null)
verificar si la cookie no está definida.¿Que tal este?
Se contaron 89 bytes sin el nombre de la función.
fuente
k
podría nombrarsekey
por claridad, pero de todos modos.Aquí va ... ¡Salud!
Tenga en cuenta que hice uso de las cadenas de plantilla de ES6 para componer la expresión regex.
fuente
esto en un objeto que puede leer, escribir, sobrescribir y eliminar cookies.
fuente
Ambas funciones parecen igualmente válidas en términos de lectura de cookies. Sin embargo, puede eliminar algunos bytes (y realmente está entrando en el territorio de Code Golf aquí):
Todo lo que hice con esto es colapsar todas las declaraciones de variables en una declaración var, eliminar los segundos argumentos innecesarios en las llamadas a la subcadena y reemplazar la llamada charAt en una desreferencia de matriz.
Esto todavía no es tan corto como la segunda función que proporcionó, pero incluso eso puede tener algunos bytes eliminados:
Cambié la primera subexpresión en la expresión regular para que sea una subexpresión de captura, y cambié el resultado [1] parte a resultado [2] para coincidir con este cambio; También se eliminaron los parens innecesarios en torno al resultado [2].
fuente
Para eliminar realmente la mayor hinchazón posible, considere no usar una función de envoltura:
Mientras esté familiarizado con RegEx, ese código es razonablemente limpio y fácil de leer.
fuente
(editar: publicó la versión incorrecta primero ... y una no funcional en eso. Actualizada a actual, que utiliza una función de desempaquetado que es muy similar al segundo ejemplo).
Buena idea en el primer ejemplo cwolves. 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 en busca de eso.
fuente
Usando la respuesta de cwolves, pero no usando un cierre ni un hash precalculado:
... y minificando ...
... es igual a 127 bytes.
fuente
Aquí está la solución más simple usando funciones de cadena javascript.
fuente
La siguiente función permitirá diferenciar entre cadenas vacías y cookies indefinidas. Las cookies no definidas volverán correctamente
undefined
y no una cadena vacía a diferencia de algunas de las otras respuestas aquí. Pero no funcionará en IE7 y versiones posteriores, ya que no permiten el acceso a la matriz a los índices de cadena.fuente