Ответ 1
Функция из W3CSchool неверна. Он терпит неудачу, если есть несколько файлов cookie, которые имеют такой же суффикс, как:
ffoo=bar; foo=baz
При поиске foo
он вернет значение ffoo вместо foo.
Теперь вот что я хотел бы сделать. Прежде всего, вам нужно узнать синтаксис того, как переносятся файлы cookie. Первоначальная спецификация Netscapes (есть только копии, доступные как этот в haxx.se) использует точки с запятой для разделения нескольких файлов cookie, в то время как каждая пара имен/значений имеет следующий синтаксис:
NAME
=
VALUE
Эта строка представляет собой последовательность символов, исключая запятую, запятую и пробел. Если необходимо поместить такие данные в имя или значение, рекомендуется использовать какой-либо метод кодирования, такой как кодировка URL style%XX
, хотя никакая кодировка не определена или не требуется.
Таким образом, разбиение строки document.cookie
на полуколоны или запятые является жизнеспособным вариантом.
Кроме того, 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
Хотя оба разрешены, запятые являются предпочтительными, поскольку они являются разделителями по умолчанию элементов списка в HTTP.
Примечание. Для обратной совместимости разделитель в заголовке файла cookie является точкой с запятой (
;
). Сервер также должен принимать запятую (,
) как разделитель между значениями cookie для будущей совместимости.
Кроме того, пара имя/значение имеет некоторые дополнительные ограничения, поскольку VALUE также может быть кавычкой, указанной в RFC 2616:
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^`a-z|~]+)=([!#$%&'*+\-.0-9A-Z^`a-z|~]*|"(?:[\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];
}