JavaScriptでCookieを読み取るための、最短、正確、クロスブラウザ互換の方法は何ですか?
非常に多くの場合、スタンドアロンスクリプト(外部の依存関係を持たない場合)を作成するときに、Cookieを読み取るための関数を追加し、通常は QuirksMode.org readCookie()
メソッドにフォールバックします。 (280バイト、216縮小)
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;
}
それは仕事をしますが、そのい、そして毎回かなりの肥大化を追加します。
jQuery.cookie というメソッドは、次のようなものを使用します(変更、165バイト、125縮小):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
注これは「コードゴルフ」競技ではありません:私は正当に私のreadCookie関数のサイズを小さくし、私が持っている解決策を確実にすることに興味があります有効です。
現在のベスト投票の回答よりも短く、信頼性が高く、パフォーマンスが高い:
function getCookieValue(a) {
var b = document.cookie.match('(^|[^;]+)\\s*' + a + '\\s*=\\s*([^;]+)');
return b ? b.pop() : '';
}
(編集:'(^|;)\\s*'
=> '(^|[^;]+)\\s*'
、以前は最初のCookieでのみ機能していました)
さまざまなアプローチのパフォーマンス比較を以下に示します。
http://jsperf.com/get-cookie-value-regex-vs-array-functions
アプローチに関する注意:
正規表現のアプローチは、ほとんどのブラウザで最速であるだけでなく、最短の機能ももたらします。さらに、 公式仕様(RFC 2109) に従って、document.cookie内のCookieを区切るセミコロンの後のスペースはオプションであり、そうでないことを示す引数を作成できることを指摘する必要があります。頼りました。さらに、等号(=)の前後に空白を含めることができ、この潜在的な空白を信頼できるdocument.cookieパーサーに組み込む必要があるという引数を作成できます。上記の正規表現は、上記の空白条件の両方を考慮しています。
これは一度だけ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 bytes
にわずかに圧縮された独自の例:
function read_cookie(k,r){return(r=RegExp('(^|; )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
1文字の関数名にすると110 bytes
に、encodeURIComponent
をドロップすると90 bytes
になります。
私はそれを73 bytes
に落としましたが、公平に言うと、readCookie
という名前の場合は82 bytes
であり、その後encodeURIComponent
を追加する場合は102 bytes
です:
function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]}
質問に基づいて、私はこの機能のいくつかの仮定/要件が含まれると信じています:
"foo:bar[0]"
を使用して関数を呼び出すと、「文字通り」「foo:bar [0]」という名前のクッキーが返されます。これらの仮定の下では、encodeURIComponent
/decodeURIComponent
を使用してはならないことは明らかです;そうすることは、Cookieを設定するコードもこれらの関数を使用してCookieをエンコードしたことを前提としています。
Cookie名に特殊文字を含めることができる場合、正規表現のアプローチは問題になります。 jQuery.cookieは、Cookieを保存するときにCookie名(実際には名前と値の両方)をエンコードし、Cookieを取得するときに名前をデコードすることで、この問題を回避します。 正規表現ソリューションは次のとおりです。
完全に制御するCookieのみを読み取る場合を除き、document.cookie
から直接Cookieを読み取りし、結果をキャッシュしないことをお勧めしますdocument.cookie
を再度読み取らずにキャッシュが無効かどうかを知る方法。
(document.cookies
へのアクセスと解析はキャッシュを使用するよりも若干遅くなりますが、CookieはDOM /レンダーツリーで役割を果たさないため、DOMの他の部分の読み取りほど遅くはありません。)
PPKの(ループベースの)関数に基づいたCode Golfの答えは次のとおりです。
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(n){n+='=';for(var a=document.cookie.split(/;\s*/),i=a.length-1;i>=0;i--)if(!a[i].indexOf(n))return a[i].replace(n,'');}
更新:本当に正規表現ソリューションが必要な場合:
function readCookie(name) {
return (name = new RegExp('(?:^|;\\s*)' + ('' + name).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '=([^;]*)').exec(document.cookie)) && name[1];
}
この エスケープ RegExpオブジェクトを構築する前のCookie名の特殊文字。縮小すると、これは134文字になります(関数名はカウントしません):
function readCookie(n){return(n=new RegExp('(?:^|;\\s*)'+(''+n).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,'\\$&')+'=([^;]*)').exec(document.cookie))&&n[1];}
Ruduとcwolvesがコメントで指摘しているように、正規表現をエスケープする正規表現は数文字短くすることができます。エスケープ正規表現の一貫性を保つことは良いと思います(他の場所で使用することもあります)が、それらの提案は検討する価値があります。
これらの関数は両方ともnull
またはundefined
を処理しません。つまり、「null」という名前のCookieがある場合、readCookie(null)
はその値を返します。このケースを処理する必要がある場合は、それに応じてコードを調整してください。
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
}
これはどう?
function getCookie(k){var v=document.cookie.match('(^|;) ?'+k+'=([^;]*)(;|$)');return v?v[2]:null}
関数名なしで89バイトをカウントしました。
乾杯!
function getCookie(n) {
let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`);
return a ? a[1] : '';
}
ES6のテンプレート文字列を使用して正規表現を作成したことに注意してください。
これは、Cookieの読み取り、書き込み、上書き、削除が可能なオブジェクト内にあります。
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;
}
};
これらの関数は両方とも、Cookieの読み取りに関して同じように見えます。ただし、数バイト削り取ることができます(そして、実際にここでコードゴルフの領域に入っています)。
function readCookie(name) {
var nameEQ = name + "=", ca = document.cookie.split(';'), i = 0, c;
for(;i < ca.length;i++) {
c = ca[i];
while (c[0]==' ') c = c.substring(1);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length);
}
return null;
}
これでやったことは、すべての変数宣言を1つのvarステートメントにまとめ、部分文字列の呼び出しで不要な2番目の引数を削除し、1つのcharAt呼び出しを配列参照解除に置き換えるだけです。
これはあなたが提供した2番目の関数ほど短いものではありませんが、それでも数バイトを取り出すことができます:
function read_cookie(key)
{
var result;
return (result = new RegExp('(^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? result[2] : null;
}
正規表現の最初の部分式をキャプチャ部分式に変更し、result [1]部分をこの変更に合わせてresult [2]に変更しました。 result [2]の周りの不要な括弧も削除しました。
JavaScript文字列関数を使用した最も簡単なソリューションを次に示します。
document.cookie.substring(document.cookie.indexOf("COOKIE_NAME"),
document.cookie.indexOf(";",
document.cookie.indexOf("COOKIE_NAME"))).
substr(COOKIE_NAME.length);
(編集:最初に間違ったバージョンを投稿し、その時点で機能しないバージョンを投稿しました。2番目の例によく似たunparam関数を使用する最新版に更新しました。)
最初の例のオオカミの素晴らしいアイデア。複数のサブドメインで機能するかなりコンパクトな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)
Cwolvesの答えを使用しますが、クロージャも事前計算済みハッシュも使用しません。
// 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バイトに等しい。
次の関数を使用すると、空の文字列と未定義のCookieを区別できます。未定義のCookieは、他のいくつかの回答とは異なり、空の文字列ではなくundefined
を正しく返します。ただし、IE7以前では機能しません。文字列インデックスへの配列アクセスが許可されていないためです。
function getCookie(name) {
return (document.cookie.match('(^|;) *'+name+'=([^;]*)')||"")[2];
}
可能な限り肥大化を完全に除去するには、ラッパー関数をまったく使用しないことを検討してください。
try {
var myCookie = document.cookie.match('(^|;) *myCookie=([^;]*)')[2]
} catch (_) {
// handle missing cookie
}
RegExに精通している限り、そのコードはかなりクリーンで読みやすいです。