このページは暫定ページです。正式ページは以下のページです。
URLエンコードについて
JavaScriptでは文字列をエンコードする命令が3つ用意されています。1つは古いブラウザでも利用できるescape()メソッド、次がencodeURI()、そして最後がencodeURIComponent()です。 s
encodeURI()とencodeURIComponent()はInternet Explorer 5.5以降でのみ利用できます。 Safariではescape()を使うとうまく日本語が処理できないことがあります。
encodeURI()とencodeURIComponent()の違い
文字列に「;/?:@&=+$,」が含まれる場合にエンコードするかどうかの違いがあります。encodeURI()はエンコードしませんが、encodeURIComponent()では下表のようにエンコードされます。
| 関数 | ; | / | ? | : | @ | & | = | + | $ | , |
|---|---|---|---|---|---|---|---|---|---|---|
| encodeURI() | ; | / | ? | : | @ | & | = | + | $ | , |
| encodeURIComponent() | %3B | %2F | %3F | %3A | %40 | %26 | %3D | %2B | %24 | %2C |
実際にやってみる
「;/?:@&=+$,」をエンコードしてみる
escape関数の問題点
具体的には、Microsoft Internet Explorer 6
(SP1)の場合には次のようなことが起きるはずです(念のため、発生する現象はブラウザによって異なる可能性があります)。「(お)」という名前を設定すると、MovableTypeのAuther
Nameでは%uFF08%u304A%uFF09という文字列がCookie (mtcmtauth)に格納されますが、TypeKey経由で設定されるCommenter
Nameでは%EF%BC%88%E3%81%8A%EF%BC%89という文字列がCookie (commenter_name)に格納されます。前者はescapeメソッドでデコードできますが後者はできませんから、Comment
PreviewなどでTypeKeyのCommenter Nameを表示しようとすると文字化けが生じます。
--------------------------------------------------------------------------------
そもそもCookieに格納する文字列は、UTF-8に変換された上でURIエンコーディングされることになっています。これをエンコード、デコードするJavaScriptのメソッドはencodeURI(またはencodeURIComponent)、decodeURI(またはdecodeURIComponent)です。歴史的な経緯もあり、escape、unescapeメソッドがURI文字列をハンドリングするために使われてきましたが、その動作はブラウザごとに異なるため現在は推奨されていません。事実、MSIE6では、文字列をUCS2の16進表示にした上で「%u」をプレフィクスとして付けた文字列が生成され、これはunescapeではデコードできるが、decodeURI(decodeURIComponent)ではデコードできません。逆にencodeURI(encodeURIComponent)を使って正しくURIエンコーディングされた文字列は、unescapeではデコードできません。要するにescape、unescapeメソッドは使うべきでないのです。ちなみにencodeURIとencodeURIComponent、decodeURIとdecodeURIComponentの違いはそれぞれ前者が「:/」などの予約文字を変換しないのに対して後者は変換するという違いです。したがって、URLや「:/」を含むCommenter
Nameをクッキーに格納する際は後者を使う必要があります。
encodeURIの問題点
ソースの文字コードによらず、UTF-8によりエンコードされる。これをそのままdecodeURIした場合は、これもソースの文字コードが適用されるので文字化けは発生しない。ところが、これをPHPなどのサーバーで受け取り、それをJSの引数として渡すと問題が発生する。これはサーバーのデフォルト文字コード?(内部文字コード?)がソースの文字コードと異なる場合に文字化けを起こしてしまう。これを回避するには、JSの引数として渡す際に、ソースの文字コードに変換してあげるとよい。例えばSHIFT_JISに変換するにはこのようにする。 $mm = decodeURI('<?=mb_convert_encoding($m,"SJIS")?>');
