首頁  >  問答  >  主體

css - js里var name=''张三" 那么name.length 这个属性在UTF-8 GB2312里分别等于多少?

js里var name=''张三" 那么name.length 这个属性在UTF-8 GB2312里分别等于多少?为什么???

巴扎黑巴扎黑2764 天前552

全部回覆(2)我來回復

  • 伊谢尔伦

    伊谢尔伦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呢?
    大致這樣幾種方案:

    1. 依照HTTP Header中的Content-Type: text/html;charset=gbk其中的charset值。例如你可以在PHP加上程式碼header("Content-Type: text/html;charset=gbk"),告訴瀏覽器編碼
    2. 如果HTTP Header中沒有charset的訊息,就看看HTML head中有沒有<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檔的編碼呢?類似的途徑:

    1. 根據test.js傳回的HTTP Header中的Content-Type: text/javascript;charset=gbk其中的charset值。當然如果你是file://協議,就沒這個東西了。
    2. 根據script的charset屬性值。
    3. 如果都沒有上述訊息,則認為JS與目前HTML文件,即test.html的編碼相同。 test.html的編碼怎麼判斷的前面說了。

    如果 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。

    回覆
    0
  • 阿神

    阿神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

    回覆
    0
  • 取消回覆