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

在JavaScript中,按名称读取cookie的最短函数是什么?,javascript,cookies,Javascript,Cookies,用JavaScript读取cookie的最短、准确且跨浏览器兼容的方法是什么? 通常,在构建独立脚本(我不能有任何外部依赖项)时,我发现自己添加了一个用于读取cookie的函数,并且通常依赖于该方法(280字节,216缩小) 注意这不是一场“代码高尔夫”竞赛:我有正当的兴趣缩小readCookie函数的大小,并确保我的解决方案有效 这将只命中document.cookie一次。随后的每个请求都是即时的 (function(){ var cookies; function rea

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

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


注意这不是一场“代码高尔夫”竞赛:我有正当的兴趣缩小readCookie函数的大小,并确保我的解决方案有效

这将只命中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字节

function read_cookie(k,r){return(r=RegExp('(^|; )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
如果将其设置为单字母函数名,则可以将其设置为
110字节
;如果删除
encodeURIComponent
,则可以将其设置为
90字节

我把它归结为
73字节
,但公平地说,命名为
readCookie
时是
82字节
,然后添加
encodeURIComponent
时是
102字节

function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]}
(编辑:先发布了错误的版本..然后是一个非功能版本。更新为current,它使用了与第二个示例非常相似的unparam函数。)

第一个例子中的好主意是cwolves。我在这两个基础上构建了一个相当紧凑的cookie读/写功能,可以跨多个子域工作。我想我会和大家分享一下,以防有人在这条线上寻找

(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)
  • 如果你什么都不通过,它就会被取消 将所有cookie放入cookie存储
  • 向rwCookie传递了一个cookie名称,它得到了 cookie的存储值
  • 传递cookie值后,它写入cookie并将该值放入存储器
  • 除非您指定一个会话,否则过期默认为会话

就读取cookie而言,这两个函数看起来同样有效。不过,您可以减少几个字节(它实际上已经进入了代码高尔夫领域):

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

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

  • 它将被用作库函数,因此意味着要放入任何代码库中
  • 因此,它需要在许多不同的环境中工作,即使用遗留JS代码、不同质量级别的CMSE等
  • 要与其他人编写的代码和/或您无法控制的代码交互,函数不应对cookie名称或值的编码方式做出任何假设。使用字符串调用函数
    “foo:bar[0]”
    应返回一个名为“foo:bar[0]”的cookie(字面意思)
  • 新cookie可以在页面生命周期内的任何时间写入和/或修改现有cookie
在这些假设下,显然不应使用
encodeURIComponent
/
decoduricomponent
;这样做假定设置cookie的代码也使用这些函数对其进行编码

document.cookie.substring(document.cookie.indexOf("COOKIE_NAME"), 
                          document.cookie.indexOf(";", 
                          document.cookie.indexOf("COOKIE_NAME"))).
  substr(COOKIE_NAME.length);
如果cookie名称可以包含特殊字符,则正则表达式方法会出现问题。cookie通过在存储cookie时编码cookie名称(实际上是名称和值),并在检索cookie时解码名称来解决此问题。下面是一个正则表达式解决方案

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

(访问和解析
文档时,Cookie
将比使用缓存稍微慢一点,但不会像读取DOM的其他部分那样慢,因为Cookie在DOM/渲染树中不起作用。)


基于循环的函数 下面是基于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(name) {
    return (name = new RegExp('(?:^|;\\s*)' + ('' + name).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '=([^;]*)').exec(document.cookie)) && name[1];
}
在构造RegExp对象之前,此操作将删除cookie名称中的任何特殊字符。缩小到134个字符(不包括函数名):

正如Rudu和Cwalves在评论中指出的,转义正则表达式的正则表达式可以缩短几个字符。我认为保持转义正则表达式的一致性是很好的(您可能在其他地方使用它),但是他们的建议值得考虑


笔记
这两个函数都不会处理
null
undefined
,即如果存在名为“null”的cookie,
readCookie(null)
将返回其值。如果需要处理这种情况,请相应地调整代码。

使用cWalves的答案,但不要使用闭包或预先计算的哈希:

// 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字节。

来自google 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
}
功能c(a){
变量d=[],
e=document.cookie.split(“;”);
a=RegExp(“^\\s*”+a+”=\\s*(.*?\\s*$”);
对于(var b=0;b这个怎么样

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

计算了89个字节,但没有函数名。

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

const getCookieValue = (name) => (
  document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
)
各种方法的性能比较如下所示:

Som
// 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];}}
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}
const getCookieValue = (name) => (
  document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
)
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] : '';
}
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
}
const getCookieValue = (name) => (
  document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
)
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);
    }
  }
}