[1] JavaScript の関数 escape()
, unescape()
は、文字列をパーセント符号化や %u
符号化します。
[2] URL で用いられているパーセント符号化とは互換性がなく、 URL
用としては encodeURIComponent()
, decodeURIComponent()
などが用意されています。
%u
符号化[16] %uHHHH
は、 JavaScript の関数
escape()
, unescape()
で用いられている符号化です。
URL のパーセント符号化と半ば意図的に混同され、現在でもたまに用いられています。
[17] 仕様上は URL で %u
符号化を用いることは認められていません。
[4] Latin1 文字 (U+00FF
以下) は百分率符号化されます。
[5] それ以外の文字は UTF-16 符号単位ごとに %u
を使って符号化されます。
[6] 歴史的には、JavaScript エンジンの内部コード (シフトJIS、UTF-16LE + BOM など) のまま百分率符号化されることがありました。
[18] %u
による符号化は ECMA-262 の第1版で
escape()
, unescape()
両関数の挙動として規定されました。
この挙動は紆余曲折を経て現在では各 JavaScript エンジンで実装されています。
[9] Escape ( 版) http://web.archive.org/web/20050222015746/http://www.felix.jp/~yugo/js/guide/escape.html
ECMA TC39 が ECMA-262 を制定するとき、escape および unescape は Unicode を用いると決めた。具体的には、Unicode エンコーディングが 0xFF 以下の文字は、16進法の数字二つの %HH 形式を用いる。 0xFF より大きい場合には、%uHHHH 形式を用いる。
MSIE のバージョン 4以降が用いる JScript では escape/unescape による URL エスケープが出来なくなった。
Netscape は、ECMA-262 に従わず、従来の ISO Latin-1 を使うと決定したため、Netscape Communicator 4.06 以降で用いられている JavaScript 1.3 でも escape/unescape を URL エスケープに利用できる。そのため、%uHHHH 形式はサポートされていない。
当初の実装では Mozilla でも ECMA-262 準拠で RFC 1738 非準拠の escape/unescape を使っていた。ところが、バグ報告があったため、2000年1月に従来通りの ISO Latin-1 を使った escape/unescape に変更された。
String Class を実装している js/src/jsstr.c で escape/unescape を実装している。 String Class を実装しているファイルに記述しているが、もちろん escape と unescape は Global オブジェクトのプロパティーである。実は、DOM の Window オブジェクトを実装している dom/src/base/nsJSWindow.cpp でも escape/unescape を実装している。こちらは従来通り ISO Latin-1 を使っている。 Mozilla は内部コードとして UCS-2 を用いており、読み込んだページは内部コードに変換されるが、DOM の escape/unescape は元のページの文字コードでエンコード/デコードする。
Mozilla では起動時に、SpiderMonkey の escape/unescape をいったん定義するが、その後 DOM の escape/unescape で上書きする。このため、Mozilla 上で escape/unescape を使うと ISO Latin-1 を用いた escape/unescape が呼び出され、SpiderMonkey を単体で動かした場合には ECMA-262 準拠の escape/unescape が呼ばれる。 Mozilla からは Unicode エスケープである ECMA-262 準拠の escape/unescape は利用できない。
もともと escape/unescape は JavaScript engine ではなく、Client-side 部分である libmocha で実装していたが、ECMA-262 が escape/unescape の仕様を定めたので、1998年5月に JavaScript engine で実装するように変更された。また、ECMA-262 になってスペースと "/" の扱いも変更された。「昔の libmocha の escape をエミュレートしたいのなら、第2引数で escape の振る舞いを指定しろ」というコメントが /js/src/jsstr.c に書いてある。このコメントの通り、第2引数に Bit 0, 1, 2 からなる mask を指定でき、この値に応じてスペースと "/" に対する振る舞いが変更される。 mask の値が不適切だと、"invalid string escape mask" というエラーが発生することがあるので注意すること。デフォルトが ECMA-262 の escape に対応した 7 である。ちなみに Java による JavaScript engine Rhino でも、mask 指定に対応している。
その escape/unescape だが、1999年12月に出た ECMA-262 3rd Edition では Compatibility の項に移されて、正式な仕様の一部ではなくなった。もっとも動作自体は 2nd Edition から変更されていない。
[10] Bug 22594 – [dogfood] JavaScript escape() is incompatable w/ 4.x ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=22594
[150] Bug 44272 - javascript escape and unescape don't work properly with unicode chars https://bugzilla.mozilla.org/show_bug.cgi?id=44272
[25] CGI.pm は %HHHH
の復号を実装しています (非 EBCDIC 環境のみ)。
ただしサロゲート・ペアはそのまま2文字になってしまいます。
[20] RFC 3987 は >>19 のように述べており、 %u
を使う方法を導入せずとも既存のパーセント符号化だけで同じことが実現できて互換性も高いとしています。
[3] Functions - MDC Docs ( 版) https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
The escape and unescape functions let you encode and decode strings. The escape function returns the hexadecimal encoding of an argument in the ISO Latin character set. The unescape function returns the ASCII string for the specified hexadecimal encoding value.
[14] JavaScriptにおけるURLエンコードの処理 ( ( 版)) http://www.cresc.co.jp/tech/java/URLencoding/JavaScript_URLEncoding.htm
%u
に注意が行きがちですが、 [U+0080
,U+00FF
] が%HH
となることにも注意が必要です。