web-dev-qa-db-ja.com

decodeURIComponent vs unescape、unescapeの何が問題になっていますか?

別の質問に答えるとき、私はまだescape/unescapeを使用してURLコンポーネントのコンテンツをエンコードしているという点で、Javascript/DOMの知識が少し古くなっていることに気付きました。代わりにencodeURIComponent/decodeURIComponentを使用する必要があります。

私が知りたいのは、escape/unescapeの何が問題なのですか? Unicode文字の周りに何らかの問題があるという漠然とした提案がいくつかありますが、明確な説明はありません。

私のWebエクスペリエンスはかなり偏っていて、ほとんどすべてがInternet Explorerに関連付けられた大きなイントラネットアプリを書いています。これにはescape/unescapeの多くの使用が含まれており、関連するアプリは長年にわたってUnicodeを完全にサポートしています。

それでは、escape/unescapeが持つはずのUnicode問題は何ですか?問題を実証するためのテストケースはありますか?

47
andynormancx

私が知りたいのは、エスケープ/エスケープの何が問題なのですか?

それらは「間違った」ものではなく、URI-parameter-encodingに少し似ていますが、実際にはそうではない独自の特別な文字列形式です。特に:

  • 「+」はスペースではなくプラスを意味します
  • uTF-8バイトをエンコードする代わりに、Unicode UTF-16コードポイントをエンコードするための特別な「%uNNNN」形式があります

したがって、escape()を使用してURIパラメーター値を作成すると、プラス記号またはASCII以外の文字を含む文字列に対して誤った結果が得られます。

escape()は、たとえばCookie値をエスケープするために、JavaScriptのみの内部エンコーディングスキームとして使用できます。ただし、すべてのブラウザーがencodeURIComponentをサポートするようになったため(本来はそうではありませんでした)、それよりもエスケープを優先的に使用する理由はありません。

私が知っているエスケープ/エスケープの現代的な使用法は1つだけです。これは、URIComponent処理でUTF-8処理を活用することで、UTF-8エンコーダー/デコーダーを実装する簡単な方法です。

utf8bytes= unescape(encodeURIComponent(unicodecharacters));
unicodecharacters= decodeURIComponent(escape(utf8bytes));
41
bobince

escapeは、0〜255の範囲の文字(ISO-8859-1、事実上、単一バイトで表現可能なUnicodeコードポイント)でのみ動作します。 (*)

encodeURIComponentは、javascriptが表現できるすべての文字列に対して機能します(これは、Unicodeの基本的な多言語プレーンの全範囲です。つまり、現在使用されているほとんどすべての人間の書記体系をカバーするUnicodeコードポイント0から1,114,111または0x10FFFFです)。

両方の関数は、コードポイント0〜127(US-ASCII)のみを使用するURLセーフ文字列を生成します。後者は、最初に文字列をUTF-8としてエンコードし、%XXescapeからURLセーフでないコードポイントまでおなじみの16進エンコーディング。

これは、これらのプリミティブを組み合わせてUTF-8処理の副作用を除くすべてをキャンセルすることにより、ループまたはガベージ生成なしでjavascriptで 2つのfuncall UTF-8エンコーダ/デコーダを作成 できる理由ですunescapedecodeURIComponentのバージョンは逆に同じことを行うためです。

(*)脚注:Google Chromeのような一部の最新ブラウザは、255文字を超える文字エスケープに対して元々定義されていなかった%uXXXXを生成するために調整されましたが、デコードのためのWebサーバーサポートそのエンコードは、IETF標準のUTF-8ベースのエンコードをデコードするほど実装されていません。

9
ecmanaut

最高の答えは、このウェブサイトでオンラインで作業していることです http://meyerweb.com/eric/tools/dencoder/

function decode() {
    var obj = document.getElementById('dencoder');
    var encoded = obj.value;
    obj.value = decodeURIComponent(encoded.replace(/\+/g,  " "));
}
7
ucefkh

私が遭遇したもう1つの「現代の」使用法は、無効なUTF8バイトシーケンスを含む可能性のあるURIエンコードされた文字列の解析です。特定の場合、decodeURIComponentは例外をスローできます。この例外をキャッチして、unescapeの使用にフォールバックする必要がある場合があります。

例は、Firefoxが生成した「t%FCr」としてエンコードされた「tür」です(?の後にアドレスバーに文字が貼り付けられた場合)。

5
sstur