Apa metode yang paling singkat, akurat, dan kompatibel dengan peramban silang untuk membaca cookie dalam JavaScript?
Sangat sering, ketika membangun skrip yang berdiri sendiri (di mana saya tidak dapat memiliki dependensi luar), saya menemukan diri saya menambahkan fungsi untuk membaca cookie, dan biasanya mundur pada metode QuirksMode.orgreadCookie()
(280 byte, 216 diperkecil).
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;
}
Itu melakukan pekerjaan, tapi itu jelek, dan menambahkan sedikit mengasapi setiap kali.
Metode yang menggunakan jQuery.cookie seperti ini (dimodifikasi, 165 byte, 125 diperkecil):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Perhatikan ini bukan kompetisi 'Code Golf': Saya secara sah tertarik mengurangi ukuran fungsi readCookie saya, dan memastikan solusi yang saya miliki valid.
javascript
cookies
Yahel
sumber
sumber
Jawaban:
Lebih pendek, lebih dapat diandalkan, dan lebih berkinerja daripada jawaban terbaik saat ini:
Perbandingan kinerja berbagai pendekatan ditampilkan di sini:
http://jsperf.com/get-cookie-value-regex-vs-array-functions
Beberapa catatan tentang pendekatan:
Pendekatan regex tidak hanya yang tercepat di sebagian besar browser, ia menghasilkan fungsi terpendek juga. Selain itu harus ditunjukkan bahwa sesuai dengan spesifikasi resmi (RFC 2109) , ruang setelah titik koma yang memisahkan cookie dalam dokumen.cookie adalah opsional dan argumen dapat dibuat bahwa itu tidak boleh diandalkan. Selain itu, spasi putih diizinkan sebelum dan sesudah tanda sama dengan (=) dan argumen dapat dibuat bahwa spasi putih potensial ini harus diperhitungkan dalam parser document.cookie yang dapat diandalkan. Regex di atas menyumbang kedua kondisi spasi putih di atas.
sumber
getCookieValue(a, b)
mengambil parameterb
?a
dan apa yangb
harus dilakukan.a
parameter tidak regex lolos, sementara itu bisa bermanfaat, itu tidak aman. Hal-hal sepertigetCookieValue('.*')
akan mengembalikan cookie acakIni hanya akan mencapai document.cookie SATU kali. Setiap permintaan selanjutnya akan instan.
Saya khawatir tidak ada cara yang lebih cepat dari logika umum ini kecuali Anda bebas untuk menggunakannya
.forEach
yang tergantung pada browser (bahkan saat itu Anda tidak menyimpan terlalu banyak)Contoh Anda sendiri sedikit dikompresi ke
120 bytes
:Anda bisa mendapatkannya
110 bytes
jika Anda menjadikannya nama fungsi 1 huruf,90 bytes
jika Anda menjatuhkannyaencodeURIComponent
.Saya sudah membahasnya
73 bytes
, tetapi untuk bersikap adil itu82 bytes
ketika dinamaireadCookie
dan102 bytes
kemudian menambahkanencodeURIComponent
:sumber
()
panggilan di akhir, jadi itu mendefinisikan fungsi anonim tetapi tidak pernah menjalankannya.Asumsi
Berdasarkan pertanyaan, saya percaya beberapa asumsi / persyaratan untuk fungsi ini meliputi:
"foo:bar[0]"
harus mengembalikan cookie (secara harfiah) bernama "foo: bar [0]";Di bawah asumsi ini, jelas bahwa
encodeURIComponent
/decodeURIComponent
tidak boleh digunakan ; melakukan hal itu dengan asumsi bahwa kode yang mengatur cookie juga menyandikannya menggunakan fungsi-fungsi ini.Pendekatan ekspresi reguler menjadi bermasalah jika nama cookie dapat berisi karakter khusus. jQuery.cookie mengatasi masalah ini dengan menyandikan nama cookie (sebenarnya nama dan nilai) ketika menyimpan cookie, dan mendekode nama saat mengambil cookie.Solusi ekspresi reguler di bawah.Kecuali Anda hanya membaca cookie yang Anda kontrol sepenuhnya, juga disarankan untuk membaca cookie dari
document.cookie
langsung dan tidak men-cache hasil, karena tidak ada cara untuk mengetahui apakah cache tidak valid tanpa membacadocument.cookie
lagi.(Walaupun mengakses dan menguraikan
document.cookies
akan sedikit lebih lambat daripada menggunakan cache, itu tidak akan selambat membaca bagian lain dari DOM, karena cookie tidak memainkan peran dalam pohon DOM / render.)Fungsi berbasis loop
Inilah jawaban Code Golf, berdasarkan fungsi PPK (berbasis loop):
yang ketika diperkecil, mencapai 128 karakter (tidak termasuk nama fungsi):
Fungsi berbasis ekspresi reguler
Pembaruan: Jika Anda benar-benar menginginkan solusi ekspresi reguler:
Ini lolos dari setiap karakter khusus dalam nama cookie sebelum membangun objek RegExp. Diminimalkan, ini sampai 134 karakter (tidak termasuk nama fungsi):
Seperti yang ditunjukkan oleh Rudu dan cwolves dalam komentar, regex reguler-ekspresi-pelarian dapat dipersingkat oleh beberapa karakter. Saya pikir itu akan baik untuk menjaga regex melarikan diri konsisten (Anda mungkin menggunakannya di tempat lain), tetapi saran mereka patut dipertimbangkan.
Catatan
Kedua fungsi ini tidak akan menangani
null
atauundefined
, yaitu jika ada cookie bernama "null",readCookie(null)
akan mengembalikan nilainya. Jika Anda perlu menangani kasus ini, sesuaikan kode tersebut.sumber
#\s
di akhir penggantian-Regex Anda? Pengganti generik itu dapat disederhanakan sedikit lebih jauh (-, tidak memiliki arti kecuali dalam tanda kurung yang lolos):/[[\]{}()*+?.\\^$|]/g
Itu dapat lebihencodeURIComponent
/[()*.\\]/g
new RegExp('[' + str + ']')
maka Anda ingin melarikan diri-
), jadi Anda mungkin benar bahwa itu dapat dipersingkat. Karena itu hanya akan menyimpan beberapa byte, dan keluar dari karakter tambahan tidak mempengaruhi regex akhir, saya cenderung membiarkannya seperti itu.encodeURIComponent()
dalam hal ini karena saya pikir OP sedang mencari fungsi generik yang dapat bekerja dengan nama cookie apa pun. Jika kode pihak ketiga menetapkan cookie bernama "foo: bar", menggunakanencodeURIComponent()
berarti mencoba membaca cookie yang bernama "foo% 3Abar".a<tab>b
menjadia\<tab>b
... yang bukan merupakan pelarian yang valid, meskipun demikian\<space>
). Dan # tampaknya tidak ada artinya di JS RegExencodeURIComponent
, jika cookie bernamafoo=
itu akan disimpan karenafoo%3D
tanpa meng-encode nama Anda juga tidak akan menemukannya (kode Anda tidak akan menemukannya) - tidak ada jawaban yang tepat. Jika Anda dapat mengontrol bagaimana cookie dimasukkan maka Anda dapat menyederhanakan jawaban / membuat asumsi untuk membantu mengeluarkannya. Yang paling sederhana / terbaik adalah dengan hanya menggunakan a-zA-Z0-9 untuk nama cookie dan menghindari keseluruhanencodeURIComponent
dan RegExp lolos dari kekacauan. Tapi Anda mungkin masih perlu khawatir tentangdecodeURIComponent
di nilai cookie karena itulah praktek direkomendasikan.kode dari google analytics ga.js
sumber
return d[0];
dan kemudian saya gunakanif (c('EXAMPLE_CK') == null)
untuk memeriksa apakah cookie tidak didefinisikan.Bagaimana dengan yang ini?
Dihitung 89 byte tanpa nama fungsi.
sumber
k
bisa dinamaikey
jelas, tapi toh.Ini dia .. Ceria!
Perhatikan bahwa saya menggunakan string template ES6 untuk menulis ekspresi regex.
sumber
ini di objek yang bisa Anda baca, tulis, tulis, dan hapus cookie.
sumber
Kedua fungsi ini terlihat sama validnya dalam hal membaca cookie. Anda dapat mencukur beberapa byte (dan ini benar-benar masuk ke wilayah Code Golf di sini):
Yang saya lakukan dengan ini adalah menciutkan semua deklarasi variabel menjadi satu pernyataan var, menghapus argumen kedua yang tidak perlu dalam panggilan ke substring, dan mengganti satu panggilan charAt menjadi dereference array.
Ini masih tidak sesingkat fungsi kedua yang Anda berikan, tetapi bahkan itu dapat menghilangkan beberapa byte:
Saya mengubah sub-ekspresi pertama dalam ekspresi reguler menjadi menangkap sub-ekspresi, dan mengubah hasil [1] bagian untuk menghasilkan [2] untuk bertepatan dengan perubahan ini; juga menghapus parens yang tidak perlu di sekitar hasil [2].
sumber
Untuk benar-benar menghilangkan bloat sebanyak mungkin, pertimbangkan untuk tidak menggunakan fungsi wrapper sama sekali:
Selama Anda terbiasa dengan RegEx, kode itu cukup bersih dan mudah dibaca.
sumber
(sunting: memposting versi yang salah terlebih dahulu .. dan yang tidak berfungsi pada saat itu. Diperbarui ke saat ini, yang menggunakan fungsi unparam yang mirip dengan contoh kedua.)
Ide bagus di cwolves contoh pertama. Saya membangun keduanya untuk fungsi membaca / menulis cookie yang cukup ringkas yang berfungsi di beberapa subdomain. Kupikir aku akan berbagi kalau-kalau ada orang yang berlari melintasi utas ini mencari itu.
sumber
Menggunakan jawaban cwolves, tetapi tidak menggunakan penutupan atau hash yang sudah dihitung sebelumnya:
... dan mengecilkan ...
... sama dengan 127 byte.
sumber
Berikut adalah solusi paling sederhana menggunakan fungsi string javascript.
sumber
Fungsi berikut akan memungkinkan membedakan antara string kosong dan cookie yang tidak terdefinisi. Cookie yang tidak terdefinisi akan kembali dengan benar
undefined
dan bukan string kosong seperti beberapa jawaban lain di sini. Tapi itu tidak akan berfungsi pada IE7 dan di bawah, karena mereka tidak mengizinkan akses array ke indeks string.sumber