Giả định
Dựa trên câu hỏi, tôi tin rằng một số giả định / yêu cầu cho chức năng này bao gồm:
- Nó sẽ được sử dụng như một chức năng của thư viện và do đó có nghĩa là được thả vào bất kỳ cơ sở mã nào;
- Như vậy, nó sẽ cần phải hoạt động trong nhiều môi trường khác nhau , tức là làm việc với mã JS cũ, các CMS có mức chất lượng khác nhau, v.v.;
- Để tương tác với mã được viết bởi người khác và / hoặc mã mà bạn không kiểm soát, hàm không được đưa ra bất kỳ giả định nào về cách mã hóa tên hoặc giá trị cookie . Gọi hàm bằng một chuỗi
"foo:bar[0]"
sẽ trả về một cookie (theo nghĩa đen) có tên là "foo: bar [0]";
- Cookie mới có thể được viết và / hoặc cookie hiện tại được sửa đổi tại bất kỳ thời điểm nào trong suốt vòng đời của trang.
Theo các giả định này, rõ ràng rằng encodeURIComponent
/ decodeURIComponent
không nên được sử dụng ; làm như vậy giả định rằng mã đặt cookie cũng mã hóa nó bằng các hàm này.
Cách tiếp cận biểu thức chính quy gặp vấn đề nếu tên cookie có thể chứa các ký tự đặc biệt. jQuery.cookie giải quyết vấn đề này bằng cách mã hóa tên cookie (thực tế là cả tên và giá trị) khi lưu trữ cookie và giải mã tên khi lấy cookie. Một giải pháp biểu hiện thông thường là dưới đây.
Trừ khi bạn chỉ đọc cookie mà bạn kiểm soát hoàn toàn, bạn cũng nên đọc cookie document.cookie
trực tiếp và không lưu bộ đệm kết quả, vì không có cách nào để biết liệu bộ đệm có hợp lệ hay không mà không đọc document.cookie
lại.
(Mặc dù việc truy cập và phân tích cú pháp document.cookies
sẽ chậm hơn một chút so với sử dụng bộ đệm, nhưng nó sẽ không chậm bằng việc đọc các phần khác của DOM, vì cookie không đóng vai trò trong các cây DOM / render.)
Hàm dựa trên vòng lặp
Dưới đây là câu trả lời Code Golf, dựa trên chức năng (dựa trên vòng lặp) của 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, '');
}
mà khi được rút gọn, có tới 128 ký tự (không tính tên hàm):
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,'');}
Hàm dựa trên biểu thức chính quy
Cập nhật: Nếu bạn thực sự muốn một giải pháp biểu thức chính quy:
function readCookie(name) {
return (name = new RegExp('(?:^|;\\s*)' + ('' + name).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '=([^;]*)').exec(document.cookie)) && name[1];
}
Điều này thoát khỏi bất kỳ ký tự đặc biệt nào trong tên cookie trước khi xây dựng đối tượng RegExp. Tối thiểu hóa, điều này có tới 134 ký tự (không tính tên hàm):
function readCookie(n){return(n=new RegExp('(?:^|;\\s*)'+(''+n).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,'\\$&')+'=([^;]*)').exec(document.cookie))&&n[1];}
Như Rudu và cwolves đã chỉ ra trong các bình luận, biểu thức thoát biểu thức chính quy có thể được rút ngắn bằng một vài ký tự. Tôi nghĩ sẽ tốt khi giữ regex thoát phù hợp (bạn có thể sử dụng nó ở nơi khác), nhưng đề xuất của họ rất đáng để xem xét.
Ghi chú
Cả hai chức năng này sẽ không xử lý null
hoặc undefined
, tức là nếu có một cookie có tên "null", readCookie(null)
sẽ trả về giá trị của nó. Nếu bạn cần xử lý trường hợp này, điều chỉnh mã cho phù hợp.