在JavaScript中通过名称读取cookie的最短function是什么?

什么是在JavaScript中读取cookie的最短,准确和跨浏览器兼容的方法?

通常,在构build独立脚本时(我不能有任何外部依赖关系),我发现自己添加了一个读取cookie的函数,并且通常在QuirksMode.org的readCookie()方法上回退(280字节,216 minified的。)

 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; } 

它做的工作,但它的丑陋,每增加一个臃肿。

jQuery.cookie使用类似这样的方法(修改,165字节,125缩小):

 function read_cookie(key) { var result; return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null; } 

请注意,这不是“Code Golf”竞赛:我合法地减lessreadCookie函数的大小,并确保我的解决scheme是有效的。

这将只会打一次document.cookie。 随后的每个请求都将立即生效。

 (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 })(); 

恐怕真的没有比这个通用逻辑更快的方法了,除非你可以自由地使用.forEach依赖于浏览器(即使那时你没有那么多)

你自己的例子稍微压缩到120 bytes

 function read_cookie(k,r){return(r=RegExp('(^|; )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;} 

如果您将其设置为1个字母的函数名称,则可以将其设置为110 bytes 90 bytes如果删除encodeURIComponent ,则可以将其设置为90 bytes

我已经得到了73 bytes ,但公平地说,当它命名为readCookie时为82 bytes 102 bytes ,然后在添加encodeURIComponent时为102 bytes

 function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]} 

比当前最佳投票答案更短,更可靠,更高性能:

 function getCookieValue(a) { var b = document.cookie.match('(^|;)\\s*' + a + '\\s*=\\s*([^;]+)'); return b ? b.pop() : ''; } 

这里显示了各种方法的性能比较:

http://jsperf.com/get-cookie-value-regex-vs-array-functions

关于方法的一些说明:

正则expression式不仅在大多数浏览器中是最快的,而且也是最短的函数。 此外,应该指出的是,根据官方规范(RFC 2109) ,在分隔文档cookie中的分号之后的空格是可选的,并且可以作出不应该依赖的参数。 此外,在等号(=)之前和之后允许使用空格,并且可以将这个潜在的空白分解成任何可靠的document.cookieparsing器。 上面的正则expression式解决了上述两个空白条件。

假设

基于这个问题,我相信这个function的一些假设/要求包括:

  • 它将被用作一个库函数 ,因此被放置到任何代码库中;
  • 因此,它将需要在许多不同的环境中工作,即与遗留的JS代码,各种质量级别的CMS等一起工作。
  • 要与其他人编写的代码和/或您不能控制的代码进行交互操作,函数不应对cookie名称或值的编码方式做出任何假设 。 用string"foo:bar[0]"调用该函数应该返回一个名为“foo:bar [0]”的cookie(字面上的)。
  • 在页面生命周期的任何时候, 新的cookie可以被写入和/或现有的cookie被修改

在这些假设下,显然不应该使用 encodeURIComponent / decodeURIComponent 。 这样做假定设置cookie的代码也使用这些函数对其进行了编码。

如果cookie名称可以包含特殊字符,则正则expression式方法会产生问题。 jQuery.cookie通过在存储cookie时编码cookie名称(实际上包括名称和值)以及在检索cookie时解码名称来解决此问题。 正则expression式解决scheme如下。

除非你只是在读取完全控制的cookies,否则直接从document.cookie读取cookie并不caching结果也是明智的,因为如果没有读取document.cookie ,caching是无效的。

(当访问和parsingdocument.cookies比使用caching稍微慢一点,它不会像读取DOM的其他部分一样慢,因为cookie在DOM /渲染树中不起作用。


基于循环的function

Code Golf基于PPK(基于循环的)函数进行回答:

 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, ''); } 

当缩小时,来到128个字符(不包括函数名称):

 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,'');} 

基于正则expression式的函数

更新:如果你真的想要一个正则expression式解决scheme:

 function readCookie(name) { return (name = new RegExp('(?:^|;\\s*)' + ('' + name).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '=([^;]*)').exec(document.cookie)) && name[1]; } 

在构造RegExp对象之前,这会转义 cookie名称中的任何特殊字符。 缩小,这到134个字符(不包括函数名称):

 function readCookie(n){return(n=new RegExp('(?:^|;\\s*)'+(''+n).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,'\\$&')+'=([^;]*)').exec(document.cookie))&&n[1];} 

正如Rudu和cwolves在评论中指出的那样,正则expression式转义的正则expression式可以缩短几个字符。 我认为保持转义的正则expression式是一致的(你可能在别处使用它),但是他们的build议值得考虑。


笔记

这两个函数都不会处理nullundefined ,即如果有一个名为“null”的cookie, readCookie(null)将返回它的值。 如果您需要处理这种情况,请相应地调整代码。

代码来自谷歌分析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 } 

这个怎么样?

 function getCookie(k){var v=document.cookie.match('(^|;) ?'+k+'=([^;]*)(;|$)');return v?v[2]:null} 

计数没有函数名称的89个字节。

这两个函数在读取cookie方面看起来同样有效。 虽然你可以刮掉几个字节(而且它真的进入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; } 

我所做的就是将所有variables声明合并到一个var语句中,删除调用substring中不必要的第二个参数,并将一个charAt调用replace为数组解引用。

这仍然不像你提供的第二个函数那么简短,但是即使这样也可以有几个字节:

 function read_cookie(key) { var result; return (result = new RegExp('(^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? result[2] : null; } 

我将正则expression式中的第一个子expression式更改为捕获子expression式,并将result [1]部分更改为result [2]以与此更改一致; 也删除了不必要的parens结果[2]。

这在一个对象,你可以读,写,overWrite和删除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; } }; 

这里去..干杯!

 function getCookie(n) { let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`); return a ? a[1] : ''; } 

请注意,我使用了ES6的模板string来组成正则expression式。

(编辑:错误的版本第一次..和一个非function的那个。更新到当前,它使用一个非参数函数,就像第二个例子。)

第一个例子中的好主意cwolves。 我build立了一个相当紧凑的cookie读/写function,跨多个子域的作品。 想象一下,如果其他人跑过这个线索寻找的话。

 (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) 
  • 如果你通过rwCookie没有任何东西,它会把所有的cookies存入cookie存储
  • 通过rwCookie一个cookie名称,它从存储获取该cookie的值
  • 通过cookie值,它写入cookie并将其存储在存储中
  • 除非您指定一个,否则到期默认为会话

使用cwolves的答案,但不使用闭包或预先计算的散列:

 // 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]; } } 

…和缩小…

 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];}} 

…等于127个字节。

这是使用JavaScriptstring函数的最简单的解决scheme。

 document.cookie.substring(document.cookie.indexOf("COOKIE_NAME"), document.cookie.indexOf(";", document.cookie.indexOf("COOKIE_NAME"))). substr(COOKIE_NAME.length); 

要尽可能多地去除膨胀,请考虑不要使用包装函数:

 try { var myCookie = document.cookie.match('(^|;) *myCookie=([^;]*)')[2] } catch (_) { // handle missing cookie } 

只要你熟悉RegEx,那么这个代码是相当干净和容易阅读的。