Javascript getCookie函数
我发现了两个函数来获取cookie数据,一个在w3schools.com上 ,一个在quirksmode.org上
我想知道我应该使用哪一个?
例如,我相信我在某个地方看到某些浏览器分裂的问题;
分号?
W3Schools的:
function getCookie(c_name) { if (document.cookie.length > 0) { c_start = document.cookie.indexOf(c_name + "="); if (c_start != -1) { c_start = c_start + c_name.length + 1; c_end = document.cookie.indexOf(";", c_start); if (c_end == -1) c_end = document.cookie.length; return unescape(document.cookie.substring(c_start, c_end)); } } return ""; }
怪异模式:
function readCokie(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; }
W3CSchool的function是错误的。 如果有多个具有相同后缀的Cookie,则失败:
ffoo=bar; foo=baz
当你searchfoo
,它将返回ffoo的值而不是foo 。
现在,我要做的是:首先,您需要了解cookie传输的语法。 Netscape的原始规范( 在haxx.se中只有这样的副本可用)使用分号分隔多个cookie,而每个名称/值对具有以下语法:
NAME
=
VALUE
这个string是一个字符序列,不包括分号,逗号和空格。 如果需要将这些数据放在名称或值中,build议使用某种编码方法,例如URL风格%XX
编码,尽pipe没有定义或要求编码。
因此,以分号或逗号分隔document.cookie
string是一个可行的select。
除此之外, RFC 2109还指定了Cookie由分号或逗号分隔:
cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value) cookie-value = NAME "=" VALUE [";" path] [";" domain] cookie-version = "$Version" "=" value NAME = attr VALUE = value path = "$Path" "=" value domain = "$Domain" "=" value
尽pipe两者都是允许的,但逗号是首选,因为它们是HTTP中的列表项的默认分隔符。
注意:为了向后兼容,Cookie标头中的分隔符在任何地方都是分号(
;
)。 服务器还应该接受逗号(,
)作为cookie值之间的分隔符,以便将来兼容。
此外,名称/值对还有一些限制,因为VALUE也可以是RFC 2616中指定的带引号的string:
attr = token value = token | quoted-string
所以这两个cookie版本需要分开处理:
if (typeof String.prototype.trimLeft !== "function") { String.prototype.trimLeft = function() { return this.replace(/^\s+/, ""); }; } if (typeof String.prototype.trimRight !== "function") { String.prototype.trimRight = function() { return this.replace(/\s+$/, ""); }; } if (typeof Array.prototype.map !== "function") { Array.prototype.map = function(callback, thisArg) { for (var i=0, n=this.length, a=[]; i<n; i++) { if (i in this) a[i] = callback.call(thisArg, this[i]); } return a; }; } function getCookies() { var c = document.cookie, v = 0, cookies = {}; if (document.cookie.match(/^\s*\$Version=(?:"1"|1);\s*(.*)/)) { c = RegExp.$1; v = 1; } if (v === 0) { c.split(/[,;]/).map(function(cookie) { var parts = cookie.split(/=/, 2), name = decodeURIComponent(parts[0].trimLeft()), value = parts.length > 1 ? decodeURIComponent(parts[1].trimRight()) : null; cookies[name] = value; }); } else { c.match(/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`az|~]+)=([!#$%&'*+\-.0-9A-Z^`az|~]*|"(?:[\x20-\x7E\x80\xFF]|\\[\x00-\x7F])*")(?=\s*[,;]|$)/g).map(function($0, $1) { var name = $0, value = $1.charAt(0) === '"' ? $1.substr(1, -1).replace(/\\(.)/g, "$1") : $1; cookies[name] = value; }); } return cookies; } function getCookie(name) { return getCookies()[name]; }
是的,W3Schools解决scheme是不正确的 。
对于那些喜欢它,这是一个更简单的解决scheme 。 它只是预先设置一个空格,所以对indexOf()的单个调用只返回正确的cookie。
function getCookie(c_name) { var c_value = " " + document.cookie; var c_start = c_value.indexOf(" " + c_name + "="); if (c_start == -1) { c_value = null; } else { c_start = c_value.indexOf("=", c_start) + 1; var c_end = c_value.indexOf(";", c_start); if (c_end == -1) { c_end = c_value.length; } c_value = unescape(c_value.substring(c_start,c_end)); } return c_value; }
这从w3schools是不正确的,它可能导致错误的cookie:
c_start = document.cookie.indexOf(c_name + "=");
如果你去找一个叫做foo
的cookie(我们假设它是一个现有的cookie),那么document.cookie
某个地方就是stringfoo=bar
。
但是,不能保证不会有stringxfoo=something
。 注意,这仍然包含子stringfoo=
所以w3schools代码将会find它。 如果xfoo
cookie恰好被列在第一位,那么您将会取回something
值(不正确!),而不是预期的bar
。
鉴于两个代码段之间的select,决不要去从根本上破坏的那个。