按名称获取cookie

IT技术 javascript cookies
2021-01-31 16:08:45

我有一个 getter 从 cookie 中获取值。

现在我按名称shares=名称有 2 个 cookie obligations=

我想让这个 getter 只是为了从义务 cookie 中获取值。

我该怎么做呢?因此,for将数据拆分为单独的值并将其放入数组中。

 function getCookie1() {
    // What do I have to add here to look only in the "obligations=" cookie? 
    // Because now it searches all the cookies.

    var elements = document.cookie.split('=');
    var obligations= elements[1].split('%');
    for (var i = 0; i < obligations.length - 1; i++) {
        var tmp = obligations[i].split('$');
        addProduct1(tmp[0], tmp[1], tmp[2], tmp[3]);
    }
 }
6个回答

一种避免迭代数组的方法是:

function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
}

演练

如果字符串中不存在标记,则按标记拆分字符串将生成一个包含一个字符串(相同值)的数组,或者生成一个包含两个字符串的数组,以防在字符串中找到标记。

第一个(左)元素是标记之前的字符串,第二个(右)是标记之后的字符串。

(注意:如果字符串以标记开头,则第一个元素是空字符串)

考虑到 cookie 的存储方式如下:

"{name}={value}; {name}={value}; ..."

为了检索特定的 cookie 值,我们只需要获取“; {name}=" 之后和下一个“;”之前的字符串。在我们进行任何处理之前,我们在 cookie 字符串前面加上“;”,这样每个 cookie 名称,包括第一个,都用“;”和“=”括起来:

"; {name}={value}; {name}={value}; ..."

现在,我们可以先用 "; {name}=" 分割,如果在 cookie 字符串中找到令牌(即我们有两个元素),我们将最终得到第二个元素是一个以我们的 cookie 值开头的字符串。然后我们从数组中取出它(即 pop),并重复相同的过程,但现在使用“;” 作为令牌,但这次拉出左边的字符串(即移位)以获得实际的令牌值。

@user3132564 试图编辑它,但它实际上是一个注释:当您搜索 cookie 的后缀时,此方法返回错误的值 - 如果 document.cookie 的值是“FirstName=John”并且您调用 getCookie("Name "),即使没有该名称的 cookie,您也会返回“John”。如果一个 cookie 的名称是另一个 cookie 的后缀,它也不起作用 - 如果 document.cookie 是“Name=John; LastName=Doe”,则调用 split("Name=") 返回一个包含三个字符串的数组,而该方法没有t 为 getCookie("Name") 返回正确的值。
2021-03-18 16:08:45
@DennisJaheruddin - 看起来后缀问题已修复。
2021-03-24 16:08:45
关于此答案中实现的警告:如果有多个同名 cookie,则不会返回任何 cookie 值。例如,如果为域 .stackexchange.com 和程序员.stackexchange.com 设置了一个名为 stackToken 的 cookie,那么如果您调用 getCookie("stackToken") 则不会返回任何值——parts.length 将大于 2。如果您知道同名(但不同的域和路径)的所有 cookie 值都相同,请在此处查看已接受的答案:stackoverflow.com/questions/5639346/...
2021-03-25 16:08:45
至于性能:我为提供的解决方案设置了 jsperf 测试:jsperf.com/getcookie-performance浏览器之间的性能差异很大。
2021-04-05 16:08:45
@NathanJ.Brauer 你是对的。很久以前已更新以解决该问题,但仅在更改日志中而不是在评论中进行了注释。
2021-04-07 16:08:45

我更喜欢在 cookie 上使用单个正则表达式匹配:

window.getCookie = function(name) {
  var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
  if (match) return match[2];
}

或者我们也可以用作函数,检查下面的代码。

function check_cookie_name(name) 
    {
      var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
      if (match) {
        console.log(match[2]);
      }
      else{
           console.log('--something went wrong---');
      }
   }

感谢 Scott Jungwirth 在评论中的改进。

@ScottJungwirth 是的,但是您必须更新 return 语句以返回 match[2];
2021-03-11 16:08:45
更新正则表达式以new RegExp('(^| )' + name + '=([^;]+)')避免@BrentWashburne 引发的问题。此外,我为此做了一个 jsperf 测试,得到了最高票数的答案,这个稍微领先,但代码肯定更少,更容易理解:jsperf.com/simple-get-cookie-by-name
2021-03-12 16:08:45
如果两个 cookie 具有相同的后缀,则可能会出现错误匹配。它将同时匹配xyz=valueabcxyz=valuewhen name = xyz
2021-03-30 16:08:45
@ScottJungwirth 为什么不new RegExp('(^|;)' + name + '=([^;]+)')呢?name行首或分号后面,为什么有空格``?
2021-03-31 16:08:45
unescape((document.cookie.match(key + '=([^;].+?)(;|$)') || [])[1] || '');Glize/dom/Cookies修改版
2021-04-05 16:08:45

使用 cookie 获取脚本:

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;
}

然后调用它:

var value = readCookie('obligations');

我从 quirksmode cookie 页面窃取了上面的代码。你应该阅读它

嘿,至少我相信了 :p 你怎么知道那个是原版的?
2021-03-11 16:08:45
@WillWam 考虑到 quirksmode 的长寿和声誉,我真的怀疑 PPK 是在从所有地方的 w3schools 窃取他的代码样本。
2021-03-17 16:08:45
通常可以安全地假设 W3S 把它放在那里。他们是很多 ctrl-c 代码新手的家园。
2021-03-26 16:08:45
实际上,它看起来正好相反 :) Quirksmode 是/是浏览器怪癖的好网站,那里也有一个来源。scottandrew.com
2021-04-07 16:08:45
...从 W3schools 窃取了代码。哇。w3schools.com/js/js_cookies.asp
2021-04-09 16:08:45

如果您使用 jQuery,我建议您使用此插件:

https://github.com/carhartl/jquery-cookie
https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js

<script type="text/javascript"
 src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js">

所以你可以像这样读取cookie:

var value = $.cookie("obligations");

你也可以写cookie:

$.cookie('obligations', 'new_value');
$.cookie('obligations', 'new_value', { expires: 14, path: '/' });

删除cookie:

$.removeCookie('obligations');
不知道为什么这实际上没有被选为最佳答案。是的,它是 jQuery 而不是 javascript,但同时它是 !!!!
2021-03-13 16:08:45
@rahulserver 是的,可能是 2015 年,但现在,2021 年这真的无关紧要,在我开始实现所有正则表达式函数之前,我包含了脚本并完成了。
2021-03-13 16:08:45
@Cozzbie 可能包含一个外部库(从而添加另一个 http 请求)来获取 cookie 值是一种不必要的矫枉过正。
2021-03-15 16:08:45
对于它的value,jquery-cookie已被取代js-cookiegithub.com/js-cookie/js-cookie
2021-03-29 16:08:45
我在“$.cookie”处收到错误“Uncaught ReferenceError: $ is not defined”。虽然我包含了所有必要的库,如 jquery.min.js 和这个答案中建议的库。
2021-04-07 16:08:45

使用正则表达式的其他一些答案中的方法并未涵盖所有情况,尤其是:

  1. 当 cookie 是最后一个 cookie 时。在这种情况下,cookie 值后不会有分号。
  2. 当另一个 cookie 名称以正在查找的名称结尾时。例如,您正在查找名为“one”的 cookie,并且有一个名为“done”的 cookie。
  3. 当 cookie 名称包含在正则表达式中使用时不被解释为自身的字符时,除非它们前面有反斜杠。

以下方法处理这些情况:

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

null如果未找到 cookie,这将返回如果 cookie 的值为空,它将返回一个空字符串。

笔记:

  1. 此函数假定cookie 名称区分大小写
  2. document.cookie- 当它出现在赋值的右侧时,它代表一个字符串,其中包含以分号分隔的 cookie 列表,而这些 cookie 又是name=value成对的。每个分号后似乎有一个空格。
  3. String.prototype.match()-null找不到匹配项时返回找到匹配项时返回一个数组,索引[1]处的元素是第一个匹配组的值。

正则表达式注意事项:

  1. (?:xxxx) - 形成一个不匹配的组。
  2. ^ - 匹配字符串的开头。
  3. | - 分离组的替代模式。
  4. ;\\s* - 匹配一个分号后跟零个或多个空白字符。
  5. = - 匹配一个等号。
  6. (xxxx) - 形成匹配组。
  7. [^;]*- 匹配零个或多个分号以外的字符。这意味着它将匹配最多但不包括分号或字符串末尾的字符。
这个答案是最好和最短的函数,适用于所有情况,没有错误匹配。它还对它的工作原理有最好的解释。但是,没有解释转义函数,我认为如果作者创建了 cookie,他就会知道是否需要对名称进行转义。所以我宁愿看到一个更短的函数:function getCookie(name) { var match = document.cookie.match(RegExp('(?:^|;\\s*)' + name + '=([^;]*)')); return match ? match[1] : null; }
2021-03-13 16:08:45
如果它是一个通用工具,它应该对名称进行转义,或者如果名称不能直接嵌入到正则表达式中,则应该抛出错误。知道其应用程序限制的人可以移除逃生或守卫。
2021-04-06 16:08:45