Alat pembangun · URL pengekod & penyahkod
escape() vs encodeURIComponent: bagaimana pengekodan JavaScript URL berkembang
· Latar belakang
javascript pengekodan url sejarah
JavaScript telah mempunyai tiga generasi fungsi pengekodan URL, dan yang tertua masih tersembunyi dalam kod pengeluaran. Siaran ini menerangkan apa yang escape() lakukan salah, mengapa ES3 menambah fungsi URI dan mengapa ia mengekalkan ! * ' ( ).
%u20AC dalam log warisan — cap jari yang jelas bagi escape() dan kegagalan penyahkodan yang diakibatkannya
Fail JavaScript warisan mengandungi panggilan pengekodan URL menggunakan fungsi escape() yang tidak digunakan lagi. Output dalam fail log atau mesej ralat termasuk urutan %u20AC—cap jari yang jelas bagi fungsi escape() yang tidak digunakan lagi yang tidak digunakan oleh orang lain. Urutan ini tidak sepadan dengan mana-mana pengekodan URL standard dan penyahkod yang dibina pada peraturan RFC 3986 atau WHATWG tidak akan mengenalinya. Data tidak boleh pergi balik melalui alat moden. Ia adalah tanda biasa kod yang mendahului ES3 dan tidak dikemas kini sejak 1990-an.
Fungsi escape() telah direka dalam era Netscape, sebelum JavaScript mempunyai piawaian atau peraturan pengekodan URL formal. Ia mengekodkan kebanyakan aksara bukan ASCII menggunakan tatatanda %uXXXX, kod perenambelasan empat digit yang tidak digunakan oleh orang lain dan tiada piawai yang menentukan di mana-mana sahaja. Ini masuk akal untuk penggunaan sekali sahaja dalam pelayar, tetapi ia memecahkan keserasian dengan piawaian URL dan menjadikan data mustahil untuk dinyahkod di tempat lain.
escape() dan unescape(): reka bentuk era Netscape — andaian Latin-1, ciptaan %uXXXX dan sebab ia tidak pernah sepadan dengan mana-mana standard
escape() dan unescape() menganggap input ialah Latin-1 (ISO 8859-1), pengekodan aksara yang mendahului UTF-8 dan Unicode. Mereka menukar setiap aksara kepada kod perenambelasan, menggunakan %XX untuk aksara Latin-1 tinggi bit dan %uXXXX untuk semua perkara di luar Latin-1. Aksara bukan Latin-1 seperti emoji tidak boleh diwakili sama sekali. Fungsinya ringkas dan pantas, tetapi ia juga salah sama sekali untuk mana-mana kes penggunaan moden.
Kedua-dua fungsi telah ditambahkan pada JavaScript sebelum piawaian wujud. Ia telah ditamatkan serta-merta selepas ES3 memperkenalkan pengekodan URL yang betul dalam 1999. Mereka kekal dalam JavaScript untuk keserasian ke belakang—mengalih keluarnya akan memecahkan kod purba. Tetapi sebarang kod baharu tidak boleh menggunakannya. Mereka adalah peninggalan warisan.
ES3 (1999) menambah pengekodanURI dan pengekodURIKomponen — UTF-8 peratus pengekodan sejajar dengan RFC 2396
ES3 memperkenalkan dua fungsi: encodeURI dan encodeURIComponent. Kedua-duanya melakukan pengekodan peratus UTF-8: tukar bukan ASCII aksara kepada UTF-8 bait, kemudian tulis setiap bait sebagai %HH. Kedua-duanya sejajar dengan RFC 2396, yang semasa pada masa itu. RFC 3986 datang kemudian dan tidak mengubah tingkah laku pengekodan. Fungsi-fungsi ini masih menjadi standard hari ini dan harus digunakan.
encodeURI dimaksudkan untuk pengekodan URI yang lengkap; encodeURIComponent dimaksudkan untuk mengekod komponen dalam URI, seperti nilai pertanyaan atau segmen laluan. Perbezaannya benar-benar kritikal dan mudah untuk salah faham. encodeURI mengekalkan aksara struktur seperti : / ? # @ = & dan ;. encodeURIComponent mengekod kesemuanya, menjadikannya selamat untuk dibenamkan di dalam URI yang lebih besar.
kenapa ! * ' ( ) masih dibiarkan tanpa dikod — aksara RFC 2396 'tanda' dibekukan ke dalam bahasa selepas RFC 3986 mengalihkannya
Kedua-dua fungsi membiarkan aksara ini tidak dikodkan: huruf, digit, sempang (-), garis bawah (_), noktah (.), tilde (~), dan lima tanda baca! * ' ( ). Tanda itu datang daripada RFC 2396, yang menyenaraikannya sebagai aksara "tanda" yang tidak ditempah. RFC 3986 keluar dalam 2005 dan memindahkan kelima-lima tersebut ke dalam kategori yang berbeza, tetapi JavaScript telah membekukan pengekodanURI dan pengekodanURIKomponen dalam 1999. Menukar aksara yang mereka biarkan sahaja akan memecahkan kod sedia ada, jadi mereka kekal.
Keputusan untuk memastikan lima tanda tersebut tidak dikodkan untuk keserasian ke belakang bermakna pengekodan JavaScript tidak sepadan dengan sempurna sama ada RFC 3986 atau standard WHATWG. Ia cukup dekat untuk kegunaan praktikal, dan menukarnya sekarang adalah mustahil sama sekali. Ini ialah pengajaran dalam kestabilan API: sebaik sahaja anda membekukan tingkah laku, anda tidak boleh mengubahnya walaupun standard berubah.
Contoh yang berfungsi: rentetan yang sama melalui escape, encodeURI dan encodeURIComponent — tiga output dibandingkan
Ambil rentetan "R&D (research) = café's". Jalankannya melalui escape(), encodeURI dan encodeURIComponent. escape() menghasilkan "R%26D%20(research)%20%3D%20caf%E9's", mencampurkan kurungan dan apostrof yang tidak dikodkan dengan ampersand yang dikodkan peratus dan sama. encodeURI menghasilkan "R&D%20(research)%20=%20caf%C3%A9's", meninggalkan ampersand dan sama dengan tanda sahaja kerana ia adalah struktur. encodeURIComponent menghasilkan "R%26D%20%28research%29%20%3D%20caf%C3%A9%27s", mengekodkan segala-galanya termasuk kurungan dan apostrof.
Tampal rentetan yang sama ke dalam pengekod & penyahkod URL dan tukar antara pengekodURI dan pengekodURIKomponen untuk melihat perbezaannya. Kemudian periksa apa yang akan dihasilkan oleh escape() (anda boleh memanggilnya dalam konsol pelayar, walaupun ia akan memberi amaran kepada anda). Anda melihat dengan serta-merta bahawa ketiga-tiga fungsi menghasilkan tiga keputusan yang sama sekali berbeza.
Berhijrah dari escape() — memetakan panggilan lama ke fungsi moden yang betul dan mengendalikan data %uXXXX yang disimpan
Kod lama menggunakan escape() mesti dikemas kini. Jika escape() digunakan untuk mengekod komponen URI, gantikannya dengan encodeURIComponent. Jika ia digunakan untuk mengekod URI yang lengkap, gunakan encodeURI. Untuk data tersimpan yang mengandungi urutan %uXXXX, anda memerlukan penyahkod tersuai: tukar setiap %uXXXX kepada titik kod Unicode, kemudian kumpulkan titik kod ke dalam rentetan. JavaScript terbina dalam unescape() akan membaca %uXXXX, tetapi hasilnya mungkin tidak betul UTF-8.
Selepas menggantikan escape(), uji kod dengan rentetan yang mengandungi aksara bukan ASCII, tanda baca dan aksara khas. Keluaran kini sepatutnya sepadan dengan apa yang diharapkan oleh alat dan piawaian moden. Jika kod anda mendahului ES3 dengan ketara, ia mungkin juga menggunakan corak lapuk yang lain; audit yang komprehensif adalah berbaloi.
Perkara ini tidak meliputi — API URL dan URLSearchParams, yang diliputi secara berasingan
API URL dan URLSearchParams, ditambah kemudian, menyediakan antara muka peringkat lebih tinggi untuk pembinaan URL dan pengekodan komponen. Mereka mengendalikan semua pelarian secara automatik dan sepadan dengan Standard WHATWG URL. Ia adalah cara pilihan untuk membina URL secara pengaturcaraan dalam JavaScript moden.
Siaran ini merangkumi sahaja fungsi pengekodan, bukan API peringkat tinggi tersebut. URL dan URLSearchParams menghuraikan struktur, pilih peraturan komponen dan sirikan hasilnya, manakala encodeURIComponent mengubah satu rentetan yang dibekalkan tanpa mengetahui di mana ia akan diletakkan. Perbezaan itu ialah sempadan: pindahkan panggilan escape() lama mengikut sama ada ia mengendalikan nilai atau alamat, kemudian pertimbangkan untuk menggantikan gabungan manual di sekeliling dengan API berstruktur sebagai refactor yang berasingan.
Bawa pulang: tiga fungsi, satu pasangan yang masih hidup — cara pengekod & penyahkod URL menunjukkan pengekodURI moden dan pengekodURIGelagat komponen bersebelahan
Pembangunan JavaScript moden harus menggunakan encodeURI atau encodeURIComponent, jangan sekali-kali pelepasan aksara(). Fungsi telah diseragamkan dalam 1999 dan tidak berubah sejak itu. Mereka mengekod aksara bukan ASCII sebagai UTF-8 bait dan mengendalikan aksara simpanan standard dengan betul. Alat pengekod & penyahkod URL melaksanakan kedua-dua fungsi dan membolehkan anda melihat gelagatnya secara bersebelahan, menjadikannya mudah untuk memilih yang sesuai untuk komponen anda.
Jika anda menemui %u jujukan dalam log lama atau data yang disimpan, ia adalah output escape() dan harus dipindahkan. Penghijrahan adalah mudah selepas anda mengenal pasti corak. Kod moden tidak boleh menghasilkannya.