[javascript] JavaScript에서 쿠키를 이름별로 읽는 가장 짧은 기능은 무엇입니까?

JavaScript에서 쿠키를 읽는 가장 짧고 정확하며 브라우저 간 호환 가능한 방법은 무엇입니까?

종종 독립형 스크립트를 작성하는 동안 (외부 종속성을 가질 수없는 곳) 쿠키를 읽는 기능을 추가하고 일반적으로 QuirksMode.orgreadCookie() 메서드 (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() : '';
}

다양한 접근 방식의 성능 비교는 다음과 같습니다.

http://jsperf.com/get-cookie-value-regex-vs-array-functions

접근에 대한 몇 가지 참고 사항 :

정규식 접근 방식은 대부분의 브라우저에서 가장 빠를뿐만 아니라 가장 짧은 기능도 제공합니다. 또한 공식 사양 (RFC 2109) 에 따르면 문서에서 쿠키를 분리하는 세미콜론 뒤의 공간은 선택 사항이며 의존해서는 안된다는 주장을 할 수 있음을 지적해야합니다. 또한 등호 (=) 앞뒤에 공백이 허용되며이 잠재적 공백을 신뢰할 수있는 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;}

당신은 그것을 얻을 수 110 bytes당신이 1 자로 된 함수 이름을 만들 경우, 90 bytes당신이 드롭하는 경우 encodeURIComponent.

나는 아래를받은 적이 73 bytes있지만, 그건 공정하게 82 bytes이름을 때 readCookie102 bytes때 다음 추가 encodeURIComponent:

function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]}


답변

가정

질문에 따라이 기능에 대한 몇 가지 가정 / 요구 사항은 다음과 같습니다.

  • 라이브러리 함수 로 사용 되므로 모든 코드베이스에 포함됩니다.
  • 따라서 많은 다른 환경에서 작동 해야 합니다 . 즉, 레거시 JS 코드, 다양한 수준의 품질의 CMS 등으로 작업해야합니다.
  • 다른 사람이 작성한 코드 및 / 또는 사용자가 제어하지 않는 코드와 상호 작용하기 위해이 함수 는 쿠키 이름 또는 값이 인코딩되는 방식을 가정해서는 안됩니다 . 문자열로 함수를 호출하면 "foo:bar[0]"“foo : bar [0]”이라는 쿠키 (문자 그대로)가 반환됩니다.
  • 새 쿠키는 페이지 수명 동안 언제든지 작성 하거나 기존 쿠키를 수정할 수 있습니다 .

이러한 가정 하에서, 그것은 분명하다 encodeURIComponent/는 decodeURIComponent 사용할 수 없습니다 ; 그렇게하면 쿠키를 설정 한 코드도 이러한 기능을 사용하여 쿠키를 인코딩했다고 가정합니다.

쿠키 이름에 특수 문자가 포함될 수 있으면 정규식 접근 방식에 문제가 발생합니다. jQuery.cookie는 쿠키를 저장할 때 쿠키 이름 (실제 이름과 값 모두)을 인코딩하고 쿠키를 검색 할 때 이름을 디코딩하여이 문제를 해결합니다. 정규식 솔루션은 다음과 같습니다.

완전히 제어하는 ​​쿠키 만 읽는 경우가 아니라면 다시 읽지 않고 캐시가 유효하지 않은지 알 수있는 방법이 없으므로 쿠키를 document.cookie직접 읽고 결과를 캐시하지 않는 것이 좋습니다 document.cookie.

(액세스 및 파싱 document.cookies은 캐시를 사용하는 것보다 약간 느리지 만 쿠키는 DOM / 렌더 트리에서 역할을하지 않기 때문에 DOM의 다른 부분을 읽는 것만 큼 느리지 않습니다.)


루프 기반 기능

다음은 PPK (루프 기반) 기능을 기반으로 한 코드 골프 답변입니다.

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 객체를 생성하기 전에 쿠키 이름의 특수 문자를 이스케이프 합니다. 축소 된 기능은 134 자 (함수 이름을 세지 않음)입니다.

function readCookie(n){return(n=new RegExp('(?:^|;\\s*)'+(''+n).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,'\\$&')+'=([^;]*)').exec(document.cookie))&&n[1];}

Rudu와 cwolves가 주석에서 지적했듯이 정규 표현식 이스케이프 정규 표현식은 몇 문자로 단축 될 수 있습니다. 나는 이스케이프 정규 표현식을 일관되게 유지하는 것이 좋을 것이라고 생각하지만 (다른 곳에서 사용하고있을 수도 있음) 그들의 제안은 고려할 가치가 있습니다.


노트

이러한 기능을 모두 처리하지 않습니다 null또는 undefined“널 (null)”라는 이름의 쿠키가있는 경우, 즉 readCookie(null)그 값을 반환합니다. 이 경우를 처리해야하는 경우 코드를 적절하게 조정하십시오.


답변

Google 웹 로그 분석 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의 템플릿 문자열을 사용하여 정규 표현식을 작성했습니다.


답변

쿠키를 읽고, 쓰고, 덮어 쓰고, 삭제할 수있는 객체에서

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