用JavaScript读取cookie的最短、准确且跨浏览器兼容的方法是什么?

通常,在构建独立脚本(在那里我不能有任何外部依赖)时,我发现自己添加了一个读取cookie的函数,并且通常回退到QuirksMode.org readCookie()方法(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;
}

它确实起到了作用,但它很丑,而且每次都增加了相当多的膨胀。

jQuery的方法。Cookie使用类似这样的内容(经过修改,165字节,125字节缩小):

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

请注意,这不是一场“代码高尔夫”比赛:我对减小readCookie函数的大小感兴趣,并确保我拥有的解决方案是有效的。


当前回答

就读取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;
}

我所做的就是将所有变量声明折叠成一个var语句,在调用substring时删除不必要的第二个参数,并将一个charAt调用替换为一个数组解引用。

这仍然没有你提供的第二个函数那么短,但即使是这样也会占用一些字节:

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

我将正则表达式中的第一个子表达式更改为捕获子表达式,并将结果[1]部分更改为结果[2]以与此更改相一致;还删除了结果[2]周围不必要的括号。

其他回答

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

为了真正消除尽可能多的膨胀,请考虑完全不使用包装器函数:

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

只要您熟悉RegEx,代码就相当干净且易于阅读。

获取cookie值,如果它不存在则为undefined:

document
  .cookie
  .split('; ')
  .filter(row => row.startsWith('cookie_name='))
  .map(c=>c.split('=')[1])[0];

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

const getCookieValue = (name) => (
  document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
)

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

https://jsben.ch/AhMN6

关于方法的一些注意事项:

The regex approach is not only the fastest in most browsers, it yields the shortest function as well. Additionally it should be pointed out that according to the official spec (RFC 2109), the space after the semicolon which separates cookies in the document.cookie is optional and an argument could be made that it should not be relied upon. Additionally, whitespace is allowed before and after the equals sign (=) and an argument could be made that this potential whitespace should be factored into any reliable document.cookie parser. The regex above accounts for both of the above whitespace conditions.

你可以验证一个cookie是否存在并且它有一个定义值:

function getCookie(cookiename) {
    if (typeof(cookiename) == 'string' && cookiename != '') {
        const COOKIES = document.cookie.split(';');
        for (i = 0; i < COOKIES.length; i++) {
            if (COOKIES[i].trim().startsWith(cookiename)) {
                return COOKIES[i].split('=')[1];
            }
        }
    }

    return null;
}

const COOKIE_EXAMPLE = getCookie('example');
if (COOKIE_EXAMPLE == 'stackoverflow') { ... }
// If is set a cookie named "example" with value "stackoverflow"
if (COOKIE_EXAMPLE != null) { ... }
// If is set a cookie named "example" ignoring the value

如果cookie不存在,则返回null。