Babelの問題では無く、JavaScriptを呼び出す環境の問題です。この現象を説明するにはソースファイルの文字コードとBabelの変換の動作の両方について知る必要があります。
###JavaScriptのソースファイルの文字コードについて
JavaScriptではソースファイル(.jsのファイル)の文字コードに関する規定がありません。JavaScriptでの文字列(string)はUnicodeコードポイントとして解釈され、内部ではUTF-16で管理されますが、ソースファイル自体がどの文字コードであるかは仕様で定められていません。
参考: ECMAScript® 2016 Language Specification #11.8.4String Literals
ある文字コードのソースファイルをUnicodeコードポイントに変換するのはJavaScriptエンジンの仕事です。そして、どの文字コードとして読み込むのかを決めるのもJavaScriptエンジンが行います。これは使い方やエンジンの種類によって異なります。
####HTMLから使用するJavaScript
HTMLのscript
要素でsrc
属性を使って読み込んだ場合は、デフォルトではHTML自身の文字コードになります。また、script
要素のcharset
属性で任意の文字コードに指定できます。
参考: HTML 5.1: 4.12. Scripting #4.12.1.1. Processing model より(訳は私訳)
If the <script>
element has a charset
attribute, then let encoding be the result of getting an encoding from the value of the charset
attribute.
<script>
要素がcharset
属性を持つ場合、charest
属性の値に基づいてエンコードする。
If the <script>
element does not have a charset
attribute, or if getting an encoding failed, let encoding be the same as the encoding of the document itself.
<script>
要素がcharset
属性持たない、または、文字コードの取得に失敗する場合、文書(訳注: HTML自身のこと)それ自体と同じ文字コードでエンコードする。
もし、HTMLについて<meta charset="UTF-8">
等で文字コードを指定せずに、UTF-8で書いていた場合、ブラウザによっては文字化けします。同様のことがHTMLから使用されるJavaScriptにも言えます。HTMLで指定している文字コードとJavaScriptが一致しない場合は、charset
属性を正しく設定しない限り、文字化けします。
注意して欲しいのはASCIIの部分は文字化けしないことです。一部の特殊な文字コードを除き、主流の文字コードはASCIIと互換性があり、ASCIIのみであれば文字化けすることはありません。次の注意点としてUnicodeエスケープ(\uXXXXや\u{XXXXXX}という表現)も文字化けしません。これはASCIIのみで表現されており、正しくJavaScriptの内部表現であるUTF-16になるため、ソースファイルの文字コードが何であるかという影響を受けないからです。
####ブラウザではなくJavaScriptエンジンで直接実行した場合。
node.js(内部はV8)の場合はUTF-8を前提にするようです。※ 正式な文章は見つけられませんでした。
WSH(JScript)はたしかWindows上のロケール依存だったと思います。日本語環境であればWindows31-J(Shift_JISの亜種、別名CP932)になると思われます。※ 手元ですぐに試せないので、未検証です。
SpiderMonkeyは調べてません。ごめんなさい。
###Babelでの変換でのUnicodeエスケープ
さて、Babelではどうなのか、囲み方の違いによってなぜ違うのか、を説明します。Babelで変換を行う場合、通常はnode.jsを使います。ですので、UTF-8のソースファイルを正しく解釈してくれます。しかし、"(二重引用符)の囲みと`(逆引用符)の囲みでは動作が異なります。
JavaScript
1var a_dq = "あ";
2var a_bq = `あ`;
をBabelで変換すると
JavaScript
1var a_dq = "あ";
2var a_bq = "\u3042";
になります。二重引用符の場合はそのままです。特に何も加工しません。しかし、逆引用符の場合は、Unicodeエスケープに変換されてしまいます。詳しく内部を確認しないとはっきりは言えませんが、逆引用符の場合は${...}
という所に特殊な処理が必要ですので、一度、JavaScriptとしてのUTF-16文字列として完全に読み込み、${...}
を除いたそのまま表示する部分を通常の文字列として書き込んでいるのだと思われます。このとき、ASCII文字以外は元の文字コードで直接表現可能かがわからないため、Unicodeエスケープで表現しているのだと思われます。(推測です)
このように表現が変わりました。前半で、Unicodeエスケープ文字はソースファイルの文字コードに影響を受けないと話したと思います。そうです。間違った文字コードが指定されてJavaScriptが読み込まれたとき、a_dq
(二重引用符)のところは文字化けしてしまいますが、a_bq
(逆引用符)の所は文字化けを起こしません。これが動きが違うように見えた原因です。
以上になります。対応としては、JavaScriptの文字コードを正しく指定することです。UTF-8なのに文字化けと言うことは、HTMLからの使用だと思われますが、HTMLもUTF-8にして、<meta charset="UTF-8">
を指定することが一番いい方法だと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/12/01 13:06 編集