首页  >  问答  >  正文

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

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

巴扎黑巴扎黑2764 天前553

全部回复(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 use two code units for less 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
  • 取消回复