すべてのフロントエンド エンジニアは、一度は「文字化けしたコード」の兄弟に遭遇したことがあると思います。基礎がどれほどしっかりしていても、開発中に時々「文字化けしたコード」の兄弟とお茶を飲むことは避けられません。生産工程。フロントエンド エンジニアとして、ページのエンコーディングをどのように指定しますか?ブラウザがエンコードをどのように認識するか知っていますか?
まず、非常に単純な例として、Yujian の HTML ページを使用して、さまざまなブラウザーの違いを確認します。
<!DOCTYPE html>
最も単純な HTML、<head>
和<body>
コンテンツはなく、サーバーは特定のエンコーディング ステートメントを与えず、ローカルで直接開きます各ブラウザでページのエンコーディングを確認します:
ブラウザ | 表示エンコーディング | 備考 |
---|---|---|
IE6 | UTF-8 | |
IE8 | UTF-8 | |
IE9 | GB2312 | システムデフォルト文字セット |
Firefox3.5 | GBK2312 | システムデフォルト文字セット |
Firefox4.0 | ISO-8859-1 | 西ヨーロッパ言語、英語のデフォルトのエンコーディング |
Chrome | GBK | システムのデフォルトの文字セット |
Opera | 中国語 - 自動検出 | もGB2312である必要があります |
大文字と小文字が区別されません。
HTML4 では、優先度に応じて次の 3 つの方法でページのエンコーディングを指定できます。<meta http-equiv="Content-Type">
タグを使用して宣言します。 <meta http-equiv="Content-Type">
标签来声明。
对于部分外部资源,如<script>
标签加载的js文件,可以通过标签上的charset属性声明。
这个自然没有什么疑问,需要注意的是,通过<meta http-equiv="Content-Type">
标签来声明页面的话,当浏览器遇上该标签时,如果发现自己使用的编码与标签声明的不符,是会回到头里重新解析页面的。这会导致页面的一部分被重新解析,因此如果试图使用标签的方式声明编码的话,建议将标签尽可能地写在前面。一个最佳实践是写在<head>
标签之后,任何其他标签之前。关于这一点,Google PageSpeed也有相应的介绍。
但是随着时间的推移,开发者渐渐发现了一件事。就如同DOCTYPE的最简声明一样,其实浏览器在读取<meta>
标签的编码的时候,并不是严格地按照标准进行的。总而言之,由于在HTML的解析阶段,基于在Tokenizer阶段之前就必须确定好页面的编码,因此浏览器不可能像分析DOM树一样,在DOM树构建的时候再分解<meta>
标签的结构,取出其中的http-equiv
和content
属性,再确定编码。
现实中,浏览器做了一件非常简单的事,来读取<meta>
标签定义的编码:
查找该字符串(此处还没有标签的概念,只是个字符串),找到一个子字符串"charset"。
再向后读,忽略掉所有的空格字符,找到第一个有意义的字符c。
如果c不是"="这个字符,则回到第2步继续找。
如果c是"="这个字符,继续向下走。
再跳掉所有的空格字符和单引号、双引号等,向后扫描,直到遇上单引号、双引号、空格字符、结束标签等不应该出现的字符为上,截取其中扫描得出的字符串s。
分析s,得到编码别名。
从上面的算法,不难发现,下面几种写法,其实都能让浏览器正确地识别出编码:
<meta http-equiv="Cotnent-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<meta charset=utf-8 />
<script>
タグによってロードされる js ファイルなどの一部の外部リソースについては、タグの charset 属性を通じて宣言できます。 <meta http-equiv="Content-Type">
タグを通じて宣言されている場合、このタグをロードするときに、使用するエンコーディングがタグ宣言と矛盾していることが判明した場合は、最初に戻ってページを再解析することになります。これにより、ページの一部が再解析されるため、タグを使用してエンコーディングを宣言しようとしている場合は、できるだけ早くタグを記述することをお勧めします。ベスト プラクティスは、<head>
タグの後、他のタグの前にこれを記述することです。この点に関しては、Google PageSpeedにも対応した導入がなされています。 <meta>
タグのエンコーディングを読み取るときは、標準に厳密に従っていません。全体として、HTML 解析段階では、トークナイザー段階の前にページのエンコーディングを決定する必要があるため、ブラウザーが <meta> Code> タグ構造を分解して < を取り出すことは不可能です。 code>http-equiv
属性と content
属性を使用して、エンコーディングを決定します。 🎜🎜実際には、ブラウザは <meta>
タグで定義されたエンコーディングを読み取るという非常に単純な処理を行います。 🎜🎜🎜🎜これが <meta> であることを確認してください。 code> タグは、HTML によって解析された ステータス マシンに基づいており、先頭に「<」が続きます。 " 文字 "メタ"文字列 🎜 を決定できます。 🎜🎜🎜🎜文字列を検索し (ここではラベルの概念はなく、文字列のみです)、部分文字列「charset」を見つけます。 🎜🎜🎜🎜逆方向に読み、すべてのスペース文字を無視し、最初の意味のある文字を見つけます。 c. 🎜🎜🎜🎜 c が「=」文字ではない場合は、手順 2 に戻って検索を続けます。 🎜🎜🎜🎜cが文字「=」の場合は、下に進みます。 🎜🎜🎜🎜🎜 次に、すべてのスペース文字、一重引用符、二重引用符などをスキップし、一重引用符、二重引用符、スペース文字、終了タグ、およびその他の出現すべきではない文字が見つかるまで逆方向にスキャンし、それらをインターセプトしてスキャンします。文字列 s. 🎜🎜🎜🎜 を分析し、エンコーディングのエイリアスを取得します。 🎜🎜🎜上記のアルゴリズムから、次の記述方法によって実際にブラウザがエンコーディングを正しく識別できることを見つけるのは難しくありません: 🎜🎜🎜< code ><meta http-equiv="Cotnent-Type" content="text/html; charset=utf-8" />
🎜🎜🎜🎜<meta charset="utf-8 " />
🎜🎜🎜🎜<meta charset=utf-8 />
🎜🎜🎜🎜...その他多くの奇妙な書き方。 🎜🎜🎜🎜それで、歴史が進むにつれ、ついにある日、さまざまなブラウザ メーカーが一堂に会して、この問題について議論し始めました...最終的には、彼らの実装が非常に似ていることに気づき、驚きました (おそらく、それぞれのメーカーから学んだだけかもしれません) other)、そこで彼らはこのメソッドを標準にすることに決めました...長い議論の末、最終的に、広く愛されている HTML5 のエンコーディング宣言メソッドが誕生しました。 HTML5 では、これは「メタ文字セット要素」と呼ばれ、その最も単純な形式は次のとおりです: 🎜<meta charset=utf-8>
当然这是HTML的语法,如果遵从XHTML并觉得XHTML更加亲切地话,写成<meta charset="utf-8" />
也是没问题的。
而前文所述的具体获取编码的算法也被详细地记录在案,可以在这里看到。
到了HTML5时代,标准再次对编码的声明方式做了修正和细化,总得来说有以下的区别:
HTML5允许使用BOM来决定编码,但仅支持UTF-16的BOM(即U+FEFF),且没有说明BOM指定编码的优先级如何。
HTML5添加了meta charset
标签。
HTML5规定如果一个页面没有指定编码,则使用ASCII作为其编码,而HTML4则规定浏览器可以根据所处的环境自行选择。
除了编码的基本声明方式外,标准中还有不少需要注意的细节:
如果使用<meta>
标签声明编码的话,该编码只能是ASCII的超集编码。可以简单地认为ASCII超集就是支持ASCII的256个字符的编码。
HTML5非常推荐使用UTF-8编码。
标准中提出不要使用UTF-32、JIS_C6226-1983、JIS_X0212-1990、HZ-GB-2312、JOHAB等字符集,并禁止使用CESU-8、UTF-7、BOCU-1和SCSU字符集。但事实上浏览器却至少能识别UTF-7。
对于想要严格遵守XHTML的开发者,应当使用XML声明来指定编码,即<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
。但是这个在IE6下会影响到DOCTYPE,所以开发者也不得在这一点上给予妥协,乖乖地去用HTML的声明方式。
关于现实中各编码声明方式的优先级,以及一些其他需要注意的细节,这篇文章值得一读。
尽可能使用HTTP头指定编码。
尽可能使用UTF-8,或者至少全站所有资源使用统一编码。
如果想使用UTF-16,就给文件加上BOM,以确定是Little Endian还是Big Endian的。
如果使用<meta>
标签指定编码,可以不使用http-equiv的形式,但尽可能让标签出现在前面,至少保证在任何非ASCII字符之前。
链接外部的脚本,如果无法确定编码相同的话,加上charset属性。
以上がHTML5標準学習~コーディングを詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。