在JavaScript中按名称读取cookie的最短函数是什么?

Yah*_*hel 180 javascript cookies

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

通常,在构建独立脚本(我不能拥有任何外部依赖项)时,我发现自己添加了一个用于读取cookie的函数,并且通常会回退到QuirksMode.orgreadCookie()方法(280字节,216缩小).

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;
}
Run Code Online (Sandbox Code Playgroud)

它完成了这项工作,但它的丑陋,每次都增加了相当多的膨胀.

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

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

请注意,这不是"Code Golf"竞赛:我有理由减少readCookie功能的大小,并确保我的解决方案有效.

Mar*_*ahn 181

这将只会遇到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
})();
Run Code Online (Sandbox Code Playgroud)

我担心除了你可以自由使用.forEach哪种依赖于浏览器之外,确实没有比这种通用逻辑更快的方法(即使那时你也没有那么多保存)

您自己的示例略微压缩为120 bytes:

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

110 bytes如果你把它设为1个字母的函数名,你可以得到它,90 bytes如果你放弃了encodeURIComponent.

我已经得到它下来73 bytes,但要公平它的82 bytes命名时readCookie102 bytes时再加入encodeURIComponent:

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

  • @yc,不,我没有 (16认同)
  • ...什么?差异说你做到了.http://d.pr/sSte它最后没有`()`调用,所以它定义了一个匿名函数但从不执行它. (3认同)
  • 我想你的意思是在那里设置`window.readCookie = cookies` ... (2认同)
  • @yc ......不,它不会*叹气* (2认同)
  • 在这里你去:http://jsperf.com/pre-increment-vs-post-increment我是对的,++我更快,至少如果你得到前后的价值.这就是你在for循环中所做的. (2认同)
  • 如果 cookie 值中包含等号,则此函数不会返回 cookie 的完整值。您可以通过使用 substring 删除 cookie 名称来更改此设置,而不是依赖于拆分 `cookies[C[0]] = c[i].substring(C[0].length + 1);` (2认同)
  • @StijndeWitt - 怎么**不回答这个问题?73个字节不够短吗?:)我的最后一个答案是***与下面的答案相同***,除了一些空格检查,哈哈 (2认同)

Mac*_*Mac 168

比目前最佳投票的答案更短,更可靠,更高效:

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

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

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

关于方法的一些说明:

正则表达式方法不仅是大多数浏览器中最快的方法,它还产生最短的函数.此外,应该指出的是,根据官方规范(RFC 2109),分隔文件中的cookie的分号后面的空格是可选的,并且可以说它不应该被依赖.此外,在等号(=)之前和之后允许使用空格,并且可以使该参数空白应该被分解为任何可靠的document.cookie解析器.上面的正则表达式解释了上述两种空白条件.

  • Upvoted,但不是为了可读性......花了一些时间来弄清楚`a`和`b`是做什么的. (14认同)
  • 聪明,但愚蠢的写它以节省1个字节. (9认同)
  • 为什么`getCookieValue(a,b)`参数`b`? (6认同)
  • `a`参数不是正则表达式转义,虽然它有用,但不安全.像`getCookieValue('.*')`之类的东西将返回任何随机cookie (5认同)
  • 我刚才注意到在Firefox中,我上面发布的正则表达式方法并不像循环方法那样高效.我之前运行的测试是在Chrome中完成的,其中正则表达式方法比其他方法表现得更好.尽管如此,它仍然是解决问题的最短时间. (4认同)
  • @BrentWashburne而不是写`var b =`...你在参数中有`,b`和`b =`里面的函数.您可以保存1个字节:D"var b"(4个字节)",bb"(3个字节) (2认同)
  • 除了代码高尔夫中的+1,这会使代码更好吗? (2认同)
  • 问题是字面上要求**最短的**解决方案,所以这应该是接受的答案imho.我正在寻找一个简短的代码片段来读取一个cookie,但是接受的答案给了我一个脚本来填充一个全局变量(我必须从那时开始跟踪)并且我仍然需要读取该全局变量,make确定它已初始化等.所以接受的答案是回答另一个问题:如何尽可能有效地阅读cookie. (2认同)

Jef*_* To 20

假设

基于这个问题,我认为这个功能的一些假设/要求包括:

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

根据这些假设,很明显encodeURIComponent/ decodeURIComponent 不应该使用 ; 这样做假设设置cookie的代码也使用这些函数对其进行编码.

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

除非你只是阅读你完全控制的cookie,否则建议直接读取cookiedocument.cookie而不是缓存结果,因为如果没有document.cookie再次读取,就无法知道缓存是否无效.

(虽然访问和解析document.cookies比使用缓存稍慢,但它不会像读取DOM的其他部分那么慢,因为cookie不会在DOM /渲染树中起作用.)


基于循环的功能

这里是基于PPK(基于循环)功能的Code Golf答案:

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, '');
}
Run Code Online (Sandbox Code Playgroud)

当缩小时,达到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,'');}
Run Code Online (Sandbox Code Playgroud)

基于正则表达式的函数

更新:如果您真的需要正则表达式解决方案:

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

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

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

正如Rudu和cwolves在评论中指出的那样,正则表达式逃避正则表达式可以缩短几个字符.我认为保持逃避正则表达式一致(你可能在其他地方使用它)会很好,但他们的建议值得考虑.


笔记

这两个函数都不会处理,null或者undefined如果有一个名为"null"的cookie,readCookie(null)它将返回其值.如果您需要处理这种情况,请相应地调整代码.


小智 14

谷歌分析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
}
Run Code Online (Sandbox Code Playgroud)


Sim*_*ger 9

这个怎么样?

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

计算不带函数名的89个字节.


小智 5

这是一个您可以读取、写入、覆盖和删除 cookie 的对象。

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;
    }
};
Run Code Online (Sandbox Code Playgroud)


may*_*yor 5

来了..干杯!

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

请注意,我使用 ES6 的模板字符串来组成正则表达式。


Joy*_*abu 5

以下函数将允许区分空字符串和未定义的 cookie。undefined与此处的其他一些答案不同,未定义的 cookie 将正确返回,而不是空字符串。

function getCookie(name) {
    return (document.cookie.match('(^|;) *'+name+'=([^;]*)')||[])[2];
}
Run Code Online (Sandbox Code Playgroud)

以上在我检查过的所有浏览器上对我来说都很好,但正如@vanovm 在评论中提到的那样,根据规范,键/值可能被空格包围。因此,以下更符合标准。

function getCookie(name) {
    return (document.cookie.match('(?:^|;)\\s*'+name.trim()+'\\s*=\\s*([^;]*?)\\s*(?:;|$)')||[])[1];
}
Run Code Online (Sandbox Code Playgroud)


Hen*_*han 5

现在是 2022 年,除了 Internet Explorer 之外的所有浏览器都支持URLSearchParamsAPI ( ^1 ) 和String.prototype.replaceAllAPI ( ^2 ),因此我们可以可怕地(ab)使用它们:

const cookies = new URLSearchParams(document.cookie.replaceAll('&', '%26').replaceAll('; ', '&'));
cookies.get('cookie name'); // returns undefined if not set, string otherwise
Run Code Online (Sandbox Code Playgroud)