js里var name=''张三" 那么name.length 这个属性在UTF-8 GB2312里分别等于多少?为什么???
伊谢尔伦2017-04-17 11:22:09
這個問題看來並不是簡單說說就行的。我加到回答裡吧。
首先, JavaScript中的String內部表示方式總是UTF16,而它的length也是總是按UTF16 code point去計算,簡而言之,length總是回傳字元數量,而非位元組大小!
那麼,為什麼有人測試發現對於同一個字串"张三"
,用UTF8編碼時回傳2,用GBK則得到3呢?那是因為瀏覽器沒能正確辨識文件編碼,所以判斷錯了,回傳3的結果是一個程式運行出錯的結果。
這個裡面概念還真多。先討論JS寫在HTML頁裡面的時候,然後再討論src載入外部JS的情況。
設test.html檔案本身的編碼為GBK,那麼瀏覽器載入test.html的時候,怎麼得知它的encoding呢?
大致這樣幾種方案:
Content-Type: text/html;charset=gbk
其中的charset值。例如你可以在PHP加上程式碼header("Content-Type: text/html;charset=gbk")
,告訴瀏覽器編碼<meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
或<meta charset="GBK"/>
,如果有的話,就使用這裡面指定的編碼解析HTML。注意, 在這之前如果有中文字元 很可能會被解析成亂碼: <head>
<title>可能显示成乱码</title>
<meta charset="GBK"/><!--It's too late here-->
</head>
如果以上都沒有找到charset訊息,那麼,其實還可以透過BOM來判斷,如果沒有BOM,那瀏覽器就只能去猜。具體怎麼猜,我說這個咱要知道了幹嘛?難道我們寫程式碼還能依賴瀏覽器能不能猜出這個程式迷語嗎?
如果瀏覽器最後沒能正確判斷到HTML檔案的編碼呢?那就亂碼嗆!對於HTML中的文字來講,你很容易看到,它就顯示成亂碼了。但對於JS文件,你就不那麼容易看到了,這樣:
a="两个"
alert(a+"\n"+a.length); //当a.length不为2的时候,前面a肯定显示成乱码
或問,為什麼這種情況下會輸出3呢?別問了! !
錯誤的輸入!錯誤的輸出! ,就算亂碼的情況下輸出2也當它是錯的,不值得花那篇幅去解釋這個了。
那好,你是不是想搞出一個輸出3的效果?很簡單,將下面的程式碼用UTF8編碼儲存到test.html檔案中:
<meta charset="GBK" />
<script>
a="两个"
alert(a+"\n"+a.length); //当a.length不为2的时候,前面a肯定显示成乱码
</script>
這樣,瀏覽器信了你在meta charset中指定的GBK編碼,但是實際上這個HTML檔是UTF8編碼,那它就亂碼了!
好了,再說下 src 引用外部JS的情況。
設外部JS檔test.js檔編碼為UTF8,test.html編碼為GBK透過下面的程式碼引用了這個JS檔:<script src="test.js" charset="UTF8"></script>
,那麼這個時候,瀏覽器怎麼判斷JS檔的編碼呢?類似的途徑:
Content-Type: text/javascript;charset=gbk
其中的charset值。當然如果你是file://協議,就沒這個東西了。 如果 HTML與外部JS的編碼不一致,且沒有指定<script charset="XXX">
或HTTP Header,那麼就會亂碼,也會造成前面的效果。
唉,這真TM廢話,這種問題已經有很多文章討論過了,直接去看這些文章就行了嘛!
例如這兩篇太長不看的文章:http://ued.taobao.org/blog/2011/08/encode-war/ ,http://tgideas.qq.com/webplat/info/news_version3/804/ 808/811/m579/201307/218730.shtml 。 W3C 對 script charset的說法:http://www.w3.org/TR/html5/scripting-1.html#attr-script-charset
太長不看不是好習慣! ! !
最後,最佳實踐當然是:總是用UTF8編碼,並且對於外部JS指定script charset。
阿神2017-04-17 11:22:09
要了解這個問題,我們先回到String.length
這個屬性的定義上去,讓我們去MDN查看一下:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ Global_Objects/String/length
This property returns the number of code units in the string. UTF-16, the string format used by JavaScript, uses a single 16-bit code unit to represent the most common characters, but needs to unit to represent the most common characters, but needs to wo woless commonly-used characters, so it's possible for the value returned by length to not match the actual number of characters in the string.
MDN上明確描述了JS是計算字串在utf-16
編碼下的長度。如果你的目前文件的編碼(可以從document.charset下取得)是utf-8
的話,就會回傳正確結果。如果你的檔案編碼是gb2312
的話,JavaScript不清楚你用的是gb2312
編碼,預設還是從utf-16
中查找則會出現不可預料的錯誤。解決這個問題的方法是正確設定編碼方式,<meta charset="utf-8" />
。 (這一部分非常感謝 @Jex 的詳細講解)
關於如何正確的計算中文字串的長度,或許你也可以參考這個頁面:http://www.puritys.me/docs-blog/article-107-String-Length-%E4%B8%AD %E6%96%87%E5%AD%97%E4%B8%B2%E9%95%B7%E5%BA%A6.html