Qual é o método mais curto, preciso e compatível com vários navegadores para ler um cookie em JavaScript?
Freqüentemente, ao criar scripts independentes (onde não posso ter nenhuma dependência externa), vejo-me adicionando uma função para ler cookies e geralmente recuo no método QuirksMode.orgreadCookie()
(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;
}
Ele faz o trabalho, mas é feio, e acrescenta bastante inchaço a cada vez.
O método que o jQuery.cookie usa algo assim (modificado, 165 bytes, 125 minificado):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Observe que não é uma competição de 'Code Golf': estou legitimamente interessado em reduzir o tamanho da minha função readCookie e em garantir que a solução que tenho seja válida.
javascript
cookies
Yahel
fonte
fonte
Respostas:
Mais curta, mais confiável e com melhor desempenho do que a atual resposta mais votada:
Uma comparação de desempenho de várias abordagens é mostrada aqui:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Algumas notas sobre a abordagem:
A abordagem regex não é apenas a mais rápida na maioria dos navegadores, mas também produz a função mais curta. Além disso, deve-se ressaltar que, de acordo com as especificações oficiais (RFC 2109) , o espaço após o ponto-e-vírgula que separa os cookies no document.cookie é opcional e pode-se argumentar que não deve ser invocado. Além disso, o espaço em branco é permitido antes e depois do sinal de igual (=) e pode-se argumentar que esse espaço em branco em potencial deve ser fatorado em qualquer analisador confiável de document.cookie. O regex acima é responsável por ambas as condições de espaço em branco acima.
fonte
getCookieValue(a, b)
tomar parâmetrob
?a
eb
fazer.a
O parâmetro não possui escape de regex, embora possa ser útil, não é seguro. Coisas comogetCookieValue('.*')
irá devolver qualquer cookie de aleatórioIsso só atingirá document.cookie UMA vez. Cada solicitação subsequente será instantânea.
Receio que realmente não exista uma maneira mais rápida do que essa lógica geral, a menos que você esteja livre para usar,
.forEach
dependendo do navegador (mesmo assim você não está economizando muito)Seu próprio exemplo ligeiramente compactado para
120 bytes
:Você pode obtê-lo
110 bytes
se criar um nome de função com uma letra,90 bytes
se você soltar oencodeURIComponent
.Eu já fiz isso
73 bytes
, mas para ser justo, é82 bytes
quando nomeadoreadCookie
e,102 bytes
em seguida, adicionandoencodeURIComponent
:fonte
()
chamada no final; portanto, estava definindo uma função anônima, mas nunca a executava.Premissas
Com base na pergunta, acredito que algumas suposições / requisitos para esta função incluem:
"foo:bar[0]"
deve retornar um cookie (literalmente) chamado "foo: bar [0]";Sob essas premissas, fica claro que
encodeURIComponent
/decodeURIComponent
não deve ser usado ; isso pressupõe que o código que definiu o cookie também o codificou usando essas funções.A abordagem da expressão regular fica problemática se o nome do cookie puder conter caracteres especiais. O jQuery.cookie soluciona esse problema codificando o nome do cookie (na verdade, nome e valor) ao armazenar um cookie e decodificando o nome ao recuperar um cookie.Uma solução de expressão regular está abaixo.A menos que você esteja apenas lendo os cookies que controla completamente, também seria aconselhável ler os cookies
document.cookie
diretamente e não armazenar em cache os resultados, pois não há como saber se o cache é inválido sem a leituradocument.cookie
novamente.(Embora o acesso e a análise
document.cookies
sejam um pouco mais lentos que o uso de um cache, não seria tão lento quanto a leitura de outras partes do DOM, pois os cookies não desempenham um papel nas árvores de renderização / DOM.)Função baseada em loop
Aqui está a resposta do Code Golf, com base na função do PPK (baseada em loop):
que quando compactado, possui 128 caracteres (sem contar o nome da função):
Função baseada em expressão regular
Atualização: se você realmente deseja uma solução de expressão regular:
Isso evita qualquer caractere especial no nome do cookie antes de construir o objeto RegExp. Minificado, trata-se de 134 caracteres (sem contar o nome da função):
Como Rudu e cwolves apontaram nos comentários, a expressão regular de escape de expressão regular pode ser reduzida por alguns caracteres. Eu acho que seria bom manter o regex de escape consistente (você pode usá-lo em outro lugar), mas vale a pena considerar suas sugestões.
Notas
Ambas as funções não tratam
null
ouundefined
, ou seja, se houver um cookie chamado "null",readCookie(null)
retornará seu valor. Se você precisar lidar com esse caso, adapte o código adequadamente.fonte
#\s
final da sua substituição-Regex? Isso genérico substituir pode ser simplificado um pouco mais (-, não têm qualquer significado exceto em suportes que são fugitivos):/[[\]{}()*+?.\\^$|]/g
Pode ser ainda classificador comencodeURIComponent
:/[()*.\\]/g
new RegExp('[' + str + ']')
isso, gostaria de escapar-
), então provavelmente está certo de que pode ser reduzido. Como ele salvaria apenas alguns bytes e o escape de caracteres extras não afeta o regex final, estou inclinado a deixá-lo como está.encodeURIComponent()
neste caso, porque acho que o OP está procurando por uma função genérica que possa funcionar com qualquer nome de cookie. Se o código de terceiros definir um cookie chamado "foo: bar", usarencodeURIComponent()
significa tentar ler um cookie chamado "foo% 3Abar".a<tab>b
ema\<tab>b
... o que não é uma fuga válida, embora\<space>
seja). E # parece não ter significado na JS RegExencodeURIComponent
, se um cookie foi nomeado,foo=
ele seria armazenado,foo%3D
sem codificar da mesma forma o nome que você não o encontrará (seu código não o encontrará) - não há resposta certa. Se você pode controlar como os cookies são inseridos, pode simplificar a resposta / fazer suposições para ajudar a divulgá-las. O mais simples / melhor é usar apenas a-zA-Z0-9 para o nome do cookie e evitar toda aencodeURIComponent
bagunça escapando ao RegExp. Mas você ainda pode precisar de se preocupar comdecodeURIComponent
a valor do cookie já que é uma prática recomendada.código do google analytics ga.js
fonte
return d[0];
e depoisif (c('EXAMPLE_CK') == null)
verifiquei se o cookie não está definido.Que tal este?
Contados 89 bytes sem o nome da função.
fonte
k
poderia ser nomeadokey
por clareza, mas de qualquer maneira.Aqui vai .. Saúde!
Observe que usei as seqüências de caracteres do modelo do ES6 para compor a expressão regex.
fonte
isso em um objeto que você pode ler, escrever, sobrescrever e excluir cookies.
fonte
Ambas as funções parecem igualmente válidas em termos de leitura de cookie. No entanto, você pode economizar alguns bytes (e realmente está entrando no território do Code Golf aqui):
Tudo o que fiz com isso foi recolher todas as declarações de variáveis em uma instrução var, remover os segundos argumentos desnecessários nas chamadas para substring e substituir a chamada charAt em uma desreferência de matriz.
Isso ainda não é tão curto quanto a segunda função que você forneceu, mas mesmo isso pode ter alguns bytes retirados:
Alterei a primeira subexpressão na expressão regular para ser uma subexpressão de captura e alterei a parte result [1] para result [2] para coincidir com essa alteração; também removeu as parênteses desnecessárias em torno do resultado [2].
fonte
Para realmente remover o máximo de inchaço possível, considere não usar uma função de invólucro:
Desde que você esteja familiarizado com o RegEx, esse código é razoavelmente limpo e fácil de ler.
fonte
(edit: postou a versão errada primeiro. e não funcional. Atualizada para atual, que usa uma função unparam que é muito parecida com o segundo exemplo.)
Boa ideia no primeiro exemplo cwolves. Desenvolvi os dois para uma função de leitura / gravação de cookie bastante compacta que funciona em vários subdomínios. Achei que eu iria compartilhar caso alguém mais atravesse esse segmento procurando por isso.
fonte
Usando a resposta de cwolves, mas não usando um fechamento nem um hash pré-calculado:
... e diminuindo ...
... é igual a 127 bytes.
fonte
Aqui está a solução mais simples usando funções de string javascript.
fonte
A função a seguir permitirá a diferenciação entre cadeias vazias e cookies indefinidos. Os cookies indefinidos retornam corretamente
undefined
e não são uma string vazia, ao contrário de algumas das outras respostas aqui. Mas não funcionará no IE7 e abaixo, pois eles não permitem o acesso da matriz a índices de string.fonte