如何检查cookie是否存在?

137

如何检查Cookie是否存在?

条件:

如果Cookie存在,则为真

cookie1=;cookie1=345534;
//or
cookie1=345534;cookie1=;
//or
cookie1=345534;

如果满足以下条件,则Cookie不存在:

cookie=;
//or
<blank>
22个回答

163
您可以使用要获取的cookie名称调用getCookie函数,然后检查它是否为null。请保留HTML标签。
function getCookie(name) {
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1) {
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    }
    else
    {
        begin += 2;
        var end = document.cookie.indexOf(";", begin);
        if (end == -1) {
        end = dc.length;
        }
    }
    // because unescape has been deprecated, replaced with decodeURI
    //return unescape(dc.substring(begin + prefix.length, end));
    return decodeURI(dc.substring(begin + prefix.length, end));
} 

function doSomething() {
    var myCookie = getCookie("MyCookie");

    if (myCookie == null) {
        // do cookie doesn't exist stuff;
    }
    else {
        // do cookie exists stuff
    }
}

3
既然unescape已经被弃用,那么使用decodeURIComponent代替有什么区别吗? - the_nuts
3
@the_nuts,不错的发现。我之前不知道这个。根据w3cschools中decodeURI()或decodeURIComponent可用于替换unescape,选择使用哪个可能取决于存储的内容。我选择decodeURI是因为我不希望在cookie中有编码分隔符。完整参考资料:http://www.w3schools.com/jsref/jsref_decodeuri.asp - jac
4
第一个 cookie 无法正常工作,因为变量“end”未设置。 - warch
4
这是一个很好的例子,说明w3schools不是可靠的信息来源,也表明你不应该从它那里复制/粘贴答案。如果你不参考w3schools,你就可以避免使用在js中非常常见的 == 和 !=。 - Isaac Pak
在 Express.js 中有什么办法吗? - Spacehold
显示剩余2条评论

136
我已经制作了一种不使用 jQuery 的替代版本:
document.cookie.match(/^(.*;)?\s*MyCookie\s*=\s*[^;]+(.*)?$/)

它仅测试cookie是否存在。更复杂的版本还可以返回cookie值:
value_or_null = (document.cookie.match(/^(?:.*;)?\s*MyCookie\s*=\s*([^;]+)(?:.*)?$/)||[,null])[1]

将你的cookie名称替换为MyCookie

24
很棒的清洁解决方案!如今人们太快地抓取插件了……过多的开销。这是一个非常好的解决方案! - patrick
3
这个不起作用。正则表达式缺少一个空格。应该是 document.cookie.match(/^(.;)? MyCookie=[^;]+(.)?$/),注意问号后面有一个空格。 - Bogdan M.
1
document.cookie 返回由空格分隔的 cookie,例如:cookie1=; cookie1=345534; - Bogdan M.
1
@BogdanM.:第一个 cookie 没有空格!/[ ]{0,1}/ 请看我上面的评论。 - Gabriel
7
如果您想使用一个变量:new RegExp("^(?:.;)?\s" + cookieName + "\s*=\s*([^;]+)(?:.*)?$") - josef
显示剩余3条评论

64
document.cookie.indexOf('cookie_name=');

如果该cookie不存在,它将返回-1

p.s. 它唯一的缺点是(如评论中所提到的),如果设置了名为any_prefix_cookie_name的cookie,则会出现错误。

(来源)


9
这也会匹配名称中包含该字符串的任何Cookie。例如,如果设置了cookie_name_whatever(即使没有设置cookie_name),则示例返回除“-1”以外的某些结果。另一个答案中的正则表达式版本可以解决这个问题。 - hajamie
7
虽然不是100%准确,但在大多数情况下,这已经是足够好的解决方案了。谢谢你 - 使用这个比其他解决方案中的庞大函数或复杂的正则表达式让我感觉更加舒适。 - Shane N
@hajamie 我认为使用 document.cookie.indexOf('cookie_name=') == 0; 可以解决这个问题。只有当 cookie 以所提到的文本开头时才为真,否则为假。 - Lasse Jacobs
2
@Lasse,只有在你只有这个cookie(或者它是第一个)的情况下才能这样做。document.cookie 包含了所有cookie的分号分隔列表。 - hajamie

21

这是一个老问题,但以下是我使用的方法...

function getCookie(name) {
    var match = document.cookie.match(RegExp('(?:^|;\\s*)' + name + '=([^;]*)')); 
    return match ? match[1] : null;
}

当cookie不存在或不包含所请求的名称时,它返回null
否则,将返回请求名称的值。

一个cookie不应该存在但没有值--因为这样做毫无意义。
如果不再需要,最好彻底删除。

function deleteCookie(name) {
    document.cookie = name +"=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;";
}

2
有一个非常合理的理由可以使用没有值的cookie,那就是为了表示某个东西的存在。它可以像布尔值一样使用:如果cookie存在,则为true;如果cookie不存在,则为false。 - Gus
4
这是列表中最好的方法。 - Andrew
2
为什么像这样的函数不是为我们内置的呢?26.3年前的Netscape 0.9b有cookies - 尽管所有ECMA版本都发布了,但在过去2.5十年中,获取和设置它们似乎并没有实质性的改进。 - ArtOfWarfare
2
你可以通过 return match && match[1]; 进一步简化 getCookie 函数,因为当 match 不是“正”条件时,它将返回 null - lbragile

17

注意!所选答案包含错误(Jac's answer)

如果您有多个cookie(很可能..),而且要检索的cookie是列表中的第一个,它将不会设置变量“end”,因此它将返回在document.cookie字符串中“cookieName =”后面的所有字符的字符串!

这是该函数的修订版本:

function getCookie( name ) {
    var dc,
        prefix,
        begin,
        end;
    
    dc = document.cookie;
    prefix = name + "=";
    begin = dc.indexOf("; " + prefix);
    end = dc.length; // default to end of the string

    // found, and not in first position
    if (begin !== -1) {
        // exclude the "; "
        begin += 2;
    } else {
        //see if cookie is in first position
        begin = dc.indexOf(prefix);
        // not found at all or found as a portion of another cookie name
        if (begin === -1 || begin !== 0 ) return null;
    } 

    // if we find a ";" somewhere after the prefix position then "end" is that position,
    // otherwise it defaults to the end of the string
    if (dc.indexOf(";", begin) !== -1) {
        end = dc.indexOf(";", begin);
    }

    return decodeURI(dc.substring(begin + prefix.length, end) ).replace(/\"/g, ''); 
}

只设置了一个 cookie,您的函数返回了 "cookieName="。 :-/ - Jeppe
1
@Jeppe 我已经修改了代码,使其在只有一个 cookie 时也能正常工作。我实际上趁机重构了整个函数并进行了整理,还添加了一些注释。 ;) - AndPicc
replace(/"/g, ''); 这段代码有问题,它会给我语法错误。 - Kamran Asgari
它对我起作用了,但在正则表达式中转义引号可能更好。我已经编辑了答案。现在应该也适用于您! - AndPicc

7
如果您正在使用jQuery,可以使用jquery.cookie插件。获取特定cookie的值的方法如下:
$.cookie('MyCookie'); // Returns the cookie value

3
这也假定OP正在使用jquery-cookie插件。对我造成了一些困扰,因为我正在使用jQuery,但无法在解决我要解决的任务时使用该插件。 - hippeelee
8
这不仅适用于jQuery,还需要一个jQuery插件,而您在回答中没有引用它。 - artfulhacker
1
我真的很惊讶,在2021年,Javascript没有一种简单的方法来测试一个cookie,就像使用一个内置的方法,你可以将cookie的名称作为参数添加进去。有时候JS是多么奇怪和愚蠢的语言啊。 - pjk_ok

6
请注意,如果一个 cookie 设置了安全标志,那么您无法使用 document.cookie 在客户端检查它的存在性(所有答案都在使用此方法)。这种 cookie 只能在服务器端检查。

3
我认为你是指仅限 http 的 cookies。安全的 cookies 仍然可以被客户端访问。 - carlin.scott

6

regexObject.test(字符串)比string.match(正则表达式)更快速

MDN网站描述了document.cookie的格式,并提供了一个抓取cookie的示例正则表达式(document.cookie.replace(/(?:(?:^|.*;\s*)test2\s*\=\s*([^;]*).*$)|^.*$/, "$1");)。基于此,我会选择以下代码:

/^(.*;)?\s*cookie1\s*=/.test(document.cookie);

这个问题似乎要求解决方案在 cookie 设置为已空值时返回 false。在这种情况下:
/^(.*;)?\s*cookie1\s*=\s*[^;]/.test(document.cookie);

测试

function cookieExists(input) {return /^(.*;)?\s*cookie1\s*=/.test(input);}
function cookieExistsAndNotBlank(input) {return /^(.*;)?\s*cookie1\s*=\s*[^;]/.test(input);}
var testCases = ['cookie1=;cookie1=345534;', 'cookie1=345534;cookie1=;', 'cookie1=345534;', ' cookie1 = 345534; ', 'cookie1=;', 'cookie123=345534;', 'cookie=345534;', ''];
console.table(testCases.map(function(s){return {'Test String': s, 'cookieExists': cookieExists(s), 'cookieExistsAndNotBlank': cookieExistsAndNotBlank(s)}}));

Test results (Chrome 55.0.2883.87)


我怎么能传递一个变量作为cookieName,而不是将cookieName作为字符串传递? - Learner
var name = 'cookie1'; new RegExp('^(.;)?\s' + name + '\s*=').test(document.cookie); - hajamie

2

你可以使用 document.cookie.split... 代替 cookie 变量。

var cookie = 'cookie1=s; cookie1=; cookie2=test';
var cookies = cookie.split('; ');
cookies.forEach(function(c){
  if(c.match(/cookie1=.+/))
   console.log(true);
});


2

这里有几个不错的答案。然而,我更喜欢[1]不使用正则表达式,[2]使用易于阅读的逻辑,[3]拥有一个短函数,[4]如果名称是另一个cookie名称的子字符串,则返回true。最后,[5]我们不能使用forEach循环,因为return语句无法中断它。

function cookieExists(name) {
  var cks = document.cookie.split(';');
  for(i = 0; i < cks.length; i++)
    if (cks[i].split('=')[0].trim() == name) return true;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接