用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函数的大小感兴趣,并确保我拥有的解决方案是有效的。


当前回答

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

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.

其他回答

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

使用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字节。

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

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

就读取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]周围不必要的括号。

此功能不适用于较老的浏览器,如chrome > 80。

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

我通过使用这个函数来解决这个问题,如果缺少cookie则返回undefined:

function getCookie(name) {
  // Add the = sign
  name = name + '=';

  // Get the decoded cookie
  var decodedCookie = decodeURIComponent(document.cookie);

  // Get all cookies, split on ; sign
  var cookies = decodedCookie.split(';');

  // Loop over the cookies
  for (var i = 0; i < cookies.length; i++) {
    // Define the single cookie, and remove whitespace
    var cookie = cookies[i].trim();

    // If this cookie has the name of what we are searching
    if (cookie.indexOf(name) == 0) {
      // Return everything after the cookies name
      return cookie.substring(name.length, cookie.length);
    }
  }
}

来源:https://daily-dev-tips.com/posts/vanilla-javascript-cookies-%F0%9F%8D%AA/